diff --git a/.Variations/03477b9a-860e-4887-81c3-5fe51621122c.var b/.Variations/03477b9a-860e-4887-81c3-5fe51621122c.var index 843197d010..49e0852b1d 100644 --- a/.Variations/03477b9a-860e-4887-81c3-5fe51621122c.var +++ b/.Variations/03477b9a-860e-4887-81c3-5fe51621122c.var @@ -159,6 +159,24 @@ "80294096-ae64-471a-bcf1-622684e06d56": 0 } } + }, + { + "Id": "51664792-c9f3-4512-bff3-4d4dab0f9171", + "IsPreset": true, + "ActivationIndex": 9, + "Title": "Accumulated Spin", + "PosOnCanvas": { + "X": 0.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "02f71a92-d5c8-4dd7-af5f-da12330f60eb": 0.33, + "80294096-ae64-471a-bcf1-622684e06d56": 4, + "b1c43d3b-f425-4d62-9d48-07ccb5d08707": 360.0, + "1139b245-76b4-4f51-a263-ee1a1371073f": 1.28 + } + } } ] } \ No newline at end of file diff --git a/.Variations/1192ae86-b174-4b58-9cc6-38afb666ce35.var b/.Variations/1192ae86-b174-4b58-9cc6-38afb666ce35.var new file mode 100644 index 0000000000..ee76df3bb2 --- /dev/null +++ b/.Variations/1192ae86-b174-4b58-9cc6-38afb666ce35.var @@ -0,0 +1,78 @@ +{ + "Id": "1192ae86-b174-4b58-9cc6-38afb666ce35", + "Variations": [ + { + "Id": "e08008b5-f824-42b3-a88e-20efeb944b4e", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Vertical", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "11cb8f1e-fac5-4623-b61c-d6482633e505": 60.0, + "ab3206bf-9413-4f31-9c3d-0c1fe7477862": 90.0, + "815975d2-5613-4ca8-b208-f09ac07b0518": 0.92 + } + } + }, + { + "Id": "0c1d4c8a-5f8e-469e-ae54-a075171348e0", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Crazy Twist", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "11cb8f1e-fac5-4623-b61c-d6482633e505": 60.0, + "ab3206bf-9413-4f31-9c3d-0c1fe7477862": 90.0, + "815975d2-5613-4ca8-b208-f09ac07b0518": 0.90000004, + "dfa5e772-0cb4-440f-8483-dcc89b40107d": 0.0 + } + } + }, + { + "Id": "23f205f3-cda1-43c4-907e-970bfabaa4ac", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "GhostLines", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "e94e2b7e-6f0a-42b5-bf5e-abdffe728273": 0.0107, + "11cb8f1e-fac5-4623-b61c-d6482633e505": 60.0, + "ab3206bf-9413-4f31-9c3d-0c1fe7477862": -51.0, + "815975d2-5613-4ca8-b208-f09ac07b0518": 0.02, + "dfa5e772-0cb4-440f-8483-dcc89b40107d": 0.08 + } + } + }, + { + "Id": "5f830328-9708-404d-a6bf-b9ffa3c8b66a", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "Noise Machine", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "e94e2b7e-6f0a-42b5-bf5e-abdffe728273": 0.0039999997, + "11cb8f1e-fac5-4623-b61c-d6482633e505": 60.0, + "ab3206bf-9413-4f31-9c3d-0c1fe7477862": 0.0, + "815975d2-5613-4ca8-b208-f09ac07b0518": -0.18, + "dfa5e772-0cb4-440f-8483-dcc89b40107d": 0.75 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/18d3d929-e530-45fa-9131-658368060ae2.var b/.Variations/18d3d929-e530-45fa-9131-658368060ae2.var index 3ad0dd4e98..37356fea39 100644 --- a/.Variations/18d3d929-e530-45fa-9131-658368060ae2.var +++ b/.Variations/18d3d929-e530-45fa-9131-658368060ae2.var @@ -188,6 +188,33 @@ } } } + }, + { + "Id": "5f90ebe0-c5c9-4806-8469-f993ee139664", + "IsPreset": true, + "ActivationIndex": 10, + "Title": "Particle-Streaks", + "PosOnCanvas": { + "X": 326.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7df44a8d-af20-400f-b8a7-4b2200f55ec1": { + "X": 0.2, + "Y": 2.0 + }, + "3247ff54-e470-466a-a70c-cdba1e264f6b": false, + "909bdbcd-620c-479e-b150-cb7adfbfffe8": 2, + "14e0d722-9441-4bc0-b164-e0b8cae990e3": 100.0, + "f9c698ae-3b59-4f1d-8497-c668f5037795": { + "X": 1.0, + "Y": 0.0, + "Z": 0.0 + }, + "6ac9265b-c6ae-47dc-a605-993d685edf90": 3 + } + } } ] } \ No newline at end of file diff --git a/.Variations/27b0e1af-cb2e-4603-83f9-5c9b042d87e6.var b/.Variations/27b0e1af-cb2e-4603-83f9-5c9b042d87e6.var new file mode 100644 index 0000000000..cefafc4a34 --- /dev/null +++ b/.Variations/27b0e1af-cb2e-4603-83f9-5c9b042d87e6.var @@ -0,0 +1,315 @@ +{ + "Id": "27b0e1af-cb2e-4603-83f9-5c9b042d87e6", + "Variations": [ + { + "Id": "81040fb1-e4f1-42e9-bdf1-2297874f10ef", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Default", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": {} + } + }, + { + "Id": "a075fd8b-b319-4f9f-a552-2f10d7bdd246", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Black", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 0.0 + } + } + } + }, + { + "Id": "99905de4-065a-4ea9-a13a-d171cb2e763c", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Black on white", + "PosOnCanvas": { + "X": 489.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 1.0 + } + } + } + }, + { + "Id": "6dcca860-f8c5-4480-8ec9-f0ad6e5245e7", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "White on Black", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 1.0 + } + } + } + }, + { + "Id": "0646033a-1969-4afb-a4f3-4364fbff4040", + "IsPreset": true, + "ActivationIndex": 5, + "Title": "Circle on Black", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 1.0 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.0, + "f0c128b1-27a1-42e0-a8a4-6fd94d527c05": 0.005 + } + } + }, + { + "Id": "3371513d-5b68-40b5-bde0-6a5cab62581e", + "IsPreset": true, + "ActivationIndex": 6, + "Title": "White Circle", + "PosOnCanvas": { + "X": 326.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 1.0, + "Y": 1.0, + "Z": 1.0, + "W": 0.0 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.0, + "f0c128b1-27a1-42e0-a8a4-6fd94d527c05": 0.005 + } + } + }, + { + "Id": "420429e2-3c97-4bdc-bed4-1a4e949b4ac6", + "IsPreset": true, + "ActivationIndex": 7, + "Title": "Vignette", + "PosOnCanvas": { + "X": 489.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 0.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 0.64 + }, + "37da22d0-56ca-444a-9c9d-27a70283b7c0": { + "X": 1.5899999, + "Y": 1.0 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.0, + "0c49c872-852a-4f15-8cde-f3cda743c28e": 4.1 + } + } + }, + { + "Id": "5939ac46-93b5-4f0e-9b27-44aeed7fab30", + "IsPreset": true, + "ActivationIndex": 8, + "Title": "Near death experience", + "PosOnCanvas": { + "X": 0.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 0.0, + "Z": 0.0884943, + "W": 0.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.6172249, + "Y": 0.0, + "Z": 0.007398215, + "W": 0.64 + }, + "37da22d0-56ca-444a-9c9d-27a70283b7c0": { + "X": 1.5899999, + "Y": 1.0 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.0, + "0c49c872-852a-4f15-8cde-f3cda743c28e": 4.1 + } + } + }, + { + "Id": "76d3224b-783b-4bce-8e80-a47fe1828c84", + "IsPreset": true, + "ActivationIndex": 9, + "Title": "I Love you", + "PosOnCanvas": { + "X": 163.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 0.067932725, + "Z": 0.9513418, + "W": 0.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.97512865, + "Y": 0.0, + "Z": 1.0, + "W": 0.13999999 + }, + "37da22d0-56ca-444a-9c9d-27a70283b7c0": { + "X": 1.5899999, + "Y": 1.0 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.53, + "f0c128b1-27a1-42e0-a8a4-6fd94d527c05": 3.1 + } + } + }, + { + "Id": "1e07de1d-0363-485e-a724-5a1f9a2c1999", + "IsPreset": true, + "ActivationIndex": 10, + "Title": "Sauron", + "PosOnCanvas": { + "X": 326.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.7321373, + "Y": 0.95587105, + "Z": 0.05594782, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.20270091, + "Y": 0.18065482, + "Z": 1.0, + "W": 0.0 + }, + "37da22d0-56ca-444a-9c9d-27a70283b7c0": { + "X": 0.12, + "Y": -0.49 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.53, + "f0c128b1-27a1-42e0-a8a4-6fd94d527c05": 1.5999999, + "0c49c872-852a-4f15-8cde-f3cda743c28e": -1.3999999 + } + } + }, + { + "Id": "b8129f65-41cb-4a6f-8f1d-cc791f85aae9", + "IsPreset": true, + "ActivationIndex": 11, + "Title": "Milkyway", + "PosOnCanvas": { + "X": 489.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "d2b0dd99-c289-4c1b-9335-c29a6b4a6ba3": { + "X": 1.0, + "Y": 0.91648245, + "Z": 0.5467086, + "W": 1.0 + }, + "fd05c355-7afa-4af6-9529-d4071d145d3b": { + "X": 0.11387473, + "Y": 0.52313375, + "Z": 1.0, + "W": 0.0 + }, + "37da22d0-56ca-444a-9c9d-27a70283b7c0": { + "X": 0.12, + "Y": -0.49 + }, + "33f31c62-b0ea-42f9-a226-d0f5154731ee": 1.8000001, + "f0c128b1-27a1-42e0-a8a4-6fd94d527c05": 1.16, + "0c49c872-852a-4f15-8cde-f3cda743c28e": 0.0, + "77544b82-e897-4e69-bfaf-e861891d1fd4": -250.0 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/2cc44046-2702-40d5-ab42-8b36ff3d6ca7.var b/.Variations/2cc44046-2702-40d5-ab42-8b36ff3d6ca7.var new file mode 100644 index 0000000000..4d410db906 --- /dev/null +++ b/.Variations/2cc44046-2702-40d5-ab42-8b36ff3d6ca7.var @@ -0,0 +1,84 @@ +{ + "Id": "2cc44046-2702-40d5-ab42-8b36ff3d6ca7", + "Variations": [ + { + "Id": "f03fdd35-0a0f-4ee2-b073-5495e1012429", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Radial Tunnel, maybe?", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7a0aaade-2cf4-45f8-85aa-1133278899ad": true, + "f5e93296-efe1-42e0-add8-f8b6298fe183": { + "X": 0.34, + "Y": 0.21, + "Z": 6.12 + }, + "ab591dbc-b521-4ef0-b1e2-d03ff27b959e": 1 + } + } + }, + { + "Id": "73c05407-0d14-4a4b-ab46-3483feeb57be", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Sometimes", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7a0aaade-2cf4-45f8-85aa-1133278899ad": true, + "42501a2b-4b10-43ff-8774-1e34fb868417": 0.02 + } + } + }, + { + "Id": "38bd3b32-bbd4-4a00-8baa-c51a7342c7ac", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Chaos", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7a0aaade-2cf4-45f8-85aa-1133278899ad": true, + "1f642c68-fca9-4552-bb23-9d066f4b2dda": 0.39, + "42501a2b-4b10-43ff-8774-1e34fb868417": 0.81, + "25e77db3-6ccb-4857-8dd6-e5c19395d85b": 0.54, + "ab591dbc-b521-4ef0-b1e2-d03ff27b959e": 1 + } + } + }, + { + "Id": "674cb5b5-97fa-4fcb-9814-289fb186c97e", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "Three two one", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7a0aaade-2cf4-45f8-85aa-1133278899ad": true, + "1f642c68-fca9-4552-bb23-9d066f4b2dda": 0.0, + "42501a2b-4b10-43ff-8774-1e34fb868417": 0.81, + "f5e93296-efe1-42e0-add8-f8b6298fe183": { + "X": 3.0, + "Y": 1.0, + "Z": 0.0 + }, + "ab591dbc-b521-4ef0-b1e2-d03ff27b959e": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/3352d3a1-ab04-4d0a-bb43-da69095b73fd.var b/.Variations/3352d3a1-ab04-4d0a-bb43-da69095b73fd.var index 01ef4cb8bf..7c9bf7cf9a 100644 --- a/.Variations/3352d3a1-ab04-4d0a-bb43-da69095b73fd.var +++ b/.Variations/3352d3a1-ab04-4d0a-bb43-da69095b73fd.var @@ -240,6 +240,46 @@ "5a3347a2-ba87-4b38-a1a8-94bd0ef70f48": 45.0 } } + }, + { + "Id": "3166188a-5918-40f5-b397-598784f9e563", + "IsPreset": true, + "ActivationIndex": 11, + "Title": "Z-To Center", + "PosOnCanvas": { + "X": -2.433628, + "Y": 408.81415 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "01a62754-7629-487d-a43a-f0cd2fbfafce": { + "X": 0.0, + "Y": 1.0, + "Z": 0.0 + }, + "cd917c3d-489e-4e4d-b5dc-eacc846d82ef": 270.0 + } + } + }, + { + "Id": "e1ca55fe-265f-4dc0-b91f-82e23b166fe6", + "IsPreset": true, + "ActivationIndex": 12, + "Title": "Z To outside", + "PosOnCanvas": { + "X": 160.56638, + "Y": 408.81415 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "01a62754-7629-487d-a43a-f0cd2fbfafce": { + "X": 0.0, + "Y": 1.0, + "Z": 0.0 + }, + "cd917c3d-489e-4e4d-b5dc-eacc846d82ef": 90.0 + } + } } ] } \ No newline at end of file diff --git a/.Variations/371d72b8-69d4-4ced-beda-271386ad2fd6.var b/.Variations/371d72b8-69d4-4ced-beda-271386ad2fd6.var new file mode 100644 index 0000000000..a40a8bdad3 --- /dev/null +++ b/.Variations/371d72b8-69d4-4ced-beda-271386ad2fd6.var @@ -0,0 +1,65 @@ +{ + "Id": "371d72b8-69d4-4ced-beda-271386ad2fd6", + "Variations": [ + { + "Id": "82128f28-fc60-4ba6-8b22-2fdac2b670d0", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "SoftNoice", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "2c5e5bb5-6023-4ff4-906d-d0a905110e95": 4, + "56bf96b4-e7c4-4747-b57a-64a39e0d6314": 1.61, + "b712d83b-6d89-43fb-8061-9ab9d38899a9": 1.09, + "7b9bafb9-3fee-4685-a76f-0a6c26a34399": -1.1700001 + } + } + }, + { + "Id": "3ea10e2f-fcb5-4ac1-b5e7-e2d878722a8e", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Below the ground", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "2c5e5bb5-6023-4ff4-906d-d0a905110e95": 2, + "0b11d459-01cc-4e91-99d2-37e77a0c8a35": { + "X": 0.0, + "Y": -0.11629531, + "Z": 0.0 + }, + "56bf96b4-e7c4-4747-b57a-64a39e0d6314": 0.2 + } + } + }, + { + "Id": "a3f85198-65f0-431c-9ace-b2bc127601b7", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Above ground", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "2c5e5bb5-6023-4ff4-906d-d0a905110e95": 2, + "0b11d459-01cc-4e91-99d2-37e77a0c8a35": { + "X": 0.0, + "Y": 0.17444293, + "Z": 0.0 + }, + "56bf96b4-e7c4-4747-b57a-64a39e0d6314": -0.16000003 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/37bdbafc-d14c-4b81-91c3-8f63c3b63812.var b/.Variations/37bdbafc-d14c-4b81-91c3-8f63c3b63812.var index f85a1f3d7f..c7eca54e12 100644 --- a/.Variations/37bdbafc-d14c-4b81-91c3-8f63c3b63812.var +++ b/.Variations/37bdbafc-d14c-4b81-91c3-8f63c3b63812.var @@ -19,6 +19,46 @@ "08174efd-78e5-4552-b559-5aa7b1b8c33e": true } } + }, + { + "Id": "d197ee3c-6e3f-46e0-ad7a-f8587624284b", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "For Nerds", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "8f72275d-d903-4372-852c-51c3db35fe90": false, + "d0ac63c5-639b-4b3c-b40b-348b76fa0fd2": true, + "621bf2cf-8d49-4b5f-88b9-4460045e8914": 0.02, + "b857b40b-2ca7-42a4-bebe-1cb11700ed71": 0.015000001, + "bbc26907-416d-4168-9e89-72ee1c6a530e": true + } + } + }, + { + "Id": "e2b8f43c-0ce0-4263-a038-68d48775f4a7", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Sprite Orientations", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "8f72275d-d903-4372-852c-51c3db35fe90": false, + "d0ac63c5-639b-4b3c-b40b-348b76fa0fd2": true, + "d2472768-dd40-436f-af1b-7359289b5118": false, + "621bf2cf-8d49-4b5f-88b9-4460045e8914": 0.02, + "b857b40b-2ca7-42a4-bebe-1cb11700ed71": 0.015000001, + "bbc26907-416d-4168-9e89-72ee1c6a530e": false, + "08174efd-78e5-4552-b559-5aa7b1b8c33e": true + } + } } ] } \ No newline at end of file diff --git a/.Variations/3ee3597d-dbf1-43a2-89d9-2f7b099112c7.var b/.Variations/3ee3597d-dbf1-43a2-89d9-2f7b099112c7.var index e589b6372e..620283ae6f 100644 --- a/.Variations/3ee3597d-dbf1-43a2-89d9-2f7b099112c7.var +++ b/.Variations/3ee3597d-dbf1-43a2-89d9-2f7b099112c7.var @@ -360,8 +360,8 @@ "ActivationIndex": 9, "Title": "untitled", "PosOnCanvas": { - "X": 0.0, - "Y": 0.0 + "X": -7.859024, + "Y": -7.1453705 }, "ParameterSetsForChildIds": { "00000000-0000-0000-0000-000000000000": { @@ -384,6 +384,160 @@ "19a0d33c-4c0e-40ce-8344-5ae17cf081e5": 6.3999996 } } + }, + { + "Id": "2b1e69ca-d069-4d7a-85d4-d37837defc1d", + "IsPreset": true, + "ActivationIndex": 10, + "Title": "Blue", + "PosOnCanvas": { + "X": 155.14098, + "Y": 271.8546 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7459b65d-a26c-41bf-bd72-2da6ef3aeb68": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 0.0 + }, + "3500901a-8783-4a6e-ad04-12a24021c11a": { + "X": 0.23583643, + "Y": 0.4497608, + "Z": 0.2825107, + "W": 0.58 + }, + "974fa2c6-c29b-4878-a80c-959ad329cf81": { + "X": 0.74499136, + "Y": 1.0, + "Z": 0.22884089, + "W": 1.0 + }, + "19a0d33c-4c0e-40ce-8344-5ae17cf081e5": 3.03, + "c4891643-ed6a-4af6-9a2f-02917cf26f24": { + "X": 10.0, + "Y": 9.0 + }, + "bc97a9f4-0652-4f28-b13f-717e2449c001": { + "X": 0.44, + "Y": 0.75 + }, + "2de30579-5ed6-4c62-8b49-301381acaad5": { + "X": 0.0, + "Y": 0.5 + }, + "5b146cff-3114-4bbe-b9e3-6f6aea3b2725": { + "X": 0.0, + "Y": 0.52 + }, + "3127ae86-b5b3-468c-8e69-004da3db7908": { + "X": 0.0, + "Y": 0.0 + }, + "1a4ced0e-f38e-4360-adb5-a62ffa0344e1": 0.99, + "79feb076-bce0-43eb-9d82-89d4159886ee": 0.11, + "55db762f-64e0-425f-a5ac-01f3edce113e": 0.03 + } + } + }, + { + "Id": "f68f41fd-874e-4e85-b7de-aae7a204d982", + "IsPreset": true, + "ActivationIndex": 11, + "Title": "Data Shine", + "PosOnCanvas": { + "X": 318.141, + "Y": 271.8546 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "3500901a-8783-4a6e-ad04-12a24021c11a": { + "X": 0.20254841, + "Y": 0.27423102, + "Z": 0.3, + "W": 1.0 + }, + "974fa2c6-c29b-4878-a80c-959ad329cf81": { + "X": 10.942462, + "Y": 7.798535, + "Z": 3.1803732, + "W": 1.0 + }, + "19a0d33c-4c0e-40ce-8344-5ae17cf081e5": 2.03, + "c4891643-ed6a-4af6-9a2f-02917cf26f24": { + "X": 6.0, + "Y": 9.0 + }, + "bc97a9f4-0652-4f28-b13f-717e2449c001": { + "X": 0.0, + "Y": 0.98 + }, + "2de30579-5ed6-4c62-8b49-301381acaad5": { + "X": 0.0, + "Y": -0.5 + }, + "5b146cff-3114-4bbe-b9e3-6f6aea3b2725": { + "X": 0.0, + "Y": 0.52 + }, + "1a4ced0e-f38e-4360-adb5-a62ffa0344e1": 0.62, + "79feb076-bce0-43eb-9d82-89d4159886ee": 0.11, + "55db762f-64e0-425f-a5ac-01f3edce113e": 0.01 + } + } + }, + { + "Id": "84d12b78-1ee3-4c6b-96cc-cee33a4e3c40", + "IsPreset": true, + "ActivationIndex": 12, + "Title": "DataShine Alpha", + "PosOnCanvas": { + "X": -7.859024, + "Y": 364.8546 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "7459b65d-a26c-41bf-bd72-2da6ef3aeb68": { + "X": 0.124340795, + "Y": 0.19929464, + "Z": 0.27272725, + "W": 0.0 + }, + "3500901a-8783-4a6e-ad04-12a24021c11a": { + "X": 0.20254841, + "Y": 0.27423102, + "Z": 0.3, + "W": 1.0 + }, + "974fa2c6-c29b-4878-a80c-959ad329cf81": { + "X": 10.942462, + "Y": 7.798535, + "Z": 3.1803732, + "W": 1.0 + }, + "19a0d33c-4c0e-40ce-8344-5ae17cf081e5": 2.03, + "c4891643-ed6a-4af6-9a2f-02917cf26f24": { + "X": 6.0, + "Y": 9.0 + }, + "bc97a9f4-0652-4f28-b13f-717e2449c001": { + "X": 0.0, + "Y": 0.98 + }, + "2de30579-5ed6-4c62-8b49-301381acaad5": { + "X": 0.0, + "Y": -0.5 + }, + "5b146cff-3114-4bbe-b9e3-6f6aea3b2725": { + "X": 0.0, + "Y": 0.52 + }, + "1a4ced0e-f38e-4360-adb5-a62ffa0344e1": 0.62, + "79feb076-bce0-43eb-9d82-89d4159886ee": 0.11, + "55db762f-64e0-425f-a5ac-01f3edce113e": 0.01 + } + } } ] } \ No newline at end of file diff --git a/.Variations/4499dcb1-c936-49ed-861b-2ad8ae58cb28.var b/.Variations/4499dcb1-c936-49ed-861b-2ad8ae58cb28.var new file mode 100644 index 0000000000..4992b3165e --- /dev/null +++ b/.Variations/4499dcb1-c936-49ed-861b-2ad8ae58cb28.var @@ -0,0 +1,51 @@ +{ + "Id": "4499dcb1-c936-49ed-861b-2ad8ae58cb28", + "Variations": [ + { + "Id": "d1912fe3-d30a-4800-8a28-aa58a2b38fa1", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Default", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": {} + } + }, + { + "Id": "40f7b642-a052-466c-ac4e-c4da0cb2fd02", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Additive Both Sided", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "922cf855-2676-4a96-9d90-622791a6a423": 1 + } + } + }, + { + "Id": "d47bb73a-3d3a-4891-bfbe-346b75476b84", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Use alpha cut off", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "922cf855-2676-4a96-9d90-622791a6a423": 1, + "c004d3c2-de74-48ee-9504-d7de7fe1e554": true, + "2c88e7c4-04f8-4e45-94d8-214775c5609c": true, + "72060e5d-090f-4c84-890a-ca9ee238fe82": 0.2 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/4f5999c9-8ade-4e31-8379-afb7db56e170.var b/.Variations/4f5999c9-8ade-4e31-8379-afb7db56e170.var new file mode 100644 index 0000000000..f09ff6459d --- /dev/null +++ b/.Variations/4f5999c9-8ade-4e31-8379-afb7db56e170.var @@ -0,0 +1,99 @@ +{ + "Id": "4f5999c9-8ade-4e31-8379-afb7db56e170", + "Variations": [ + { + "Id": "4a10de57-8f06-487a-aaa5-42cb4c0a4bb1", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Default", + "PosOnCanvas": { + "X": 0.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": {} + } + }, + { + "Id": "e879951a-ce27-4424-b96a-f9578a482476", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Subtle", + "PosOnCanvas": { + "X": 163.00002, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "eddf467a-d96e-4639-aa09-b49dc1775c1b": 0.25 + } + } + }, + { + "Id": "c5782bee-6d62-40d1-b75e-321801b7ebd9", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "HorizontalTwist", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "eddf467a-d96e-4639-aa09-b49dc1775c1b": 0.25, + "b04d0d69-f322-4481-9166-ca812eb35d99": { + "X": 4.0, + "Y": 0.1 + } + } + } + }, + { + "Id": "9f9bdf6a-8c37-4fc2-9027-318e516344a9", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "Border Reflection", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "0de3d1e6-63d4-4dbf-a426-cbd4e6019c45": 1.0 + } + } + }, + { + "Id": "27ca0acb-cfa0-40aa-a832-39ad2d2aaef8", + "IsPreset": true, + "ActivationIndex": 5, + "Title": "Squeeze Closeup", + "PosOnCanvas": { + "X": 163.00002, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "87264af4-0939-4aad-9a15-b79d067b9fcb": 0.24, + "d5038c16-3920-48fc-8cd8-9346b63dad7a": 2.0 + } + } + }, + { + "Id": "94d23869-56dd-4f95-ab2b-aa6e96b1943a", + "IsPreset": true, + "ActivationIndex": 6, + "Title": "Into the distance", + "PosOnCanvas": { + "X": 326.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "87264af4-0939-4aad-9a15-b79d067b9fcb": 0.004, + "d5038c16-3920-48fc-8cd8-9346b63dad7a": 8.0 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/50aab941-0a29-474a-affd-13a74ea0c780.var b/.Variations/50aab941-0a29-474a-affd-13a74ea0c780.var new file mode 100644 index 0000000000..d6342ed677 --- /dev/null +++ b/.Variations/50aab941-0a29-474a-affd-13a74ea0c780.var @@ -0,0 +1,26 @@ +{ + "Id": "50aab941-0a29-474a-affd-13a74ea0c780", + "Variations": [ + { + "Id": "6d8c3c3f-cd51-42a8-bd0d-aef926f87d6e", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Handheld Cam", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "c427d83b-1046-4b8d-b44a-e616a64a702a": { + "X": 2.06, + "Y": 0.56, + "Z": 0.76 + }, + "03df41a8-3d72-47b1-b854-81e6e59e7cb4": 0.5, + "2693cb7d-33b3-4a0c-929f-e6911d2d4a0c": 3 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/6820b166-1782-43b9-bc5c-6b4f63b16f86.var b/.Variations/6820b166-1782-43b9-bc5c-6b4f63b16f86.var index 608b5e8c0d..83bb6bf5f1 100644 --- a/.Variations/6820b166-1782-43b9-bc5c-6b4f63b16f86.var +++ b/.Variations/6820b166-1782-43b9-bc5c-6b4f63b16f86.var @@ -178,6 +178,41 @@ "f93db0c6-c5ed-40da-9677-0c284618f5bb": 3.6000001 } } + }, + { + "Id": "02fa9b95-131b-44fb-9eba-3b24a2d19c38", + "IsPreset": true, + "ActivationIndex": 7, + "Title": "From Top Left", + "PosOnCanvas": { + "X": 163.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": -0.21, + "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.62, + "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 27.0, + "03298545-a5d6-44d5-bb7c-4747172d2667": { + "X": 2.28, + "Y": 1.3 + }, + "9d5e3055-c17e-4013-963d-e17c76b707c1": { + "X": 1.3217562, + "Y": 2.0, + "Z": 1.8521526, + "W": 1.0 + }, + "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { + "X": 0.80382776, + "Y": 0.14403573, + "Z": 0.17499748, + "W": 0.6698565 + }, + "d162a7e1-1906-45bc-a896-10ee2c2483fe": 5.0, + "f93db0c6-c5ed-40da-9677-0c284618f5bb": 9.7 + } + } } ] } \ No newline at end of file diff --git a/.Variations/7a08d73e-1aea-479f-8d36-ecb119d75c3a.var b/.Variations/7a08d73e-1aea-479f-8d36-ecb119d75c3a.var new file mode 100644 index 0000000000..8766cbcdd5 --- /dev/null +++ b/.Variations/7a08d73e-1aea-479f-8d36-ecb119d75c3a.var @@ -0,0 +1,27 @@ +{ + "Id": "7a08d73e-1aea-479f-8d36-ecb119d75c3a", + "Variations": [ + { + "Id": "11ed258b-26b3-466f-85c7-b809f8f3a808", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Gravity", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "1840e5b8-2aee-44d0-b826-d34395325506": { + "X": 0.0, + "Y": -0.081, + "Z": 0.0 + }, + "4f9ab443-3885-4a57-9116-6be5824bd95b": 0.1, + "9c8c1407-bf6a-47c0-8c6c-2cd9f303151d": true, + "1f561bbd-a272-4c06-bd56-a580a2022bc6": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/87915d7b-f2aa-45da-80f9-bd1f6033d387.var b/.Variations/87915d7b-f2aa-45da-80f9-bd1f6033d387.var new file mode 100644 index 0000000000..4b93ddcac4 --- /dev/null +++ b/.Variations/87915d7b-f2aa-45da-80f9-bd1f6033d387.var @@ -0,0 +1,91 @@ +{ + "Id": "87915d7b-f2aa-45da-80f9-bd1f6033d387", + "Variations": [ + { + "Id": "8882101c-0897-4139-82b4-35a4361d4cf2", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "CrazyOrbits", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "129f21fb-3206-4b0a-b455-485f1c11bd83": { + "X": 0.0, + "Y": 0.82, + "Z": 0.0 + }, + "cbcfcceb-309b-4a25-856a-cb4eb3798cf4": 6.6000004, + "02f34a62-bd83-47ac-962a-f1af6a92f0b8": 3.1999998, + "93cae017-8bf6-44c8-9b45-8b9a4e64b9bd": -1.6000003 + } + } + }, + { + "Id": "fd7d68dc-5c71-4b4a-b8a9-f1b212ca5dfd", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "QuietLimits", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "129f21fb-3206-4b0a-b455-485f1c11bd83": { + "X": 0.0, + "Y": 0.82, + "Z": 0.0 + }, + "cbcfcceb-309b-4a25-856a-cb4eb3798cf4": 0.19, + "02f34a62-bd83-47ac-962a-f1af6a92f0b8": 3.1999998, + "93cae017-8bf6-44c8-9b45-8b9a4e64b9bd": 2.0 + } + } + }, + { + "Id": "68c5a17d-e0bf-441f-960b-47bdaddbbdd0", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "CrazyConvergenz", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "129f21fb-3206-4b0a-b455-485f1c11bd83": { + "X": 0.0, + "Y": 0.82, + "Z": 0.0 + }, + "02f34a62-bd83-47ac-962a-f1af6a92f0b8": 1.0, + "93cae017-8bf6-44c8-9b45-8b9a4e64b9bd": 0.13 + } + } + }, + { + "Id": "bb9bcf7f-4ef4-4120-ab2a-9fd667f0a283", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "LinearConvergence", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "129f21fb-3206-4b0a-b455-485f1c11bd83": { + "X": 0.0, + "Y": 0.82, + "Z": 0.0 + }, + "02f34a62-bd83-47ac-962a-f1af6a92f0b8": 0.23, + "93cae017-8bf6-44c8-9b45-8b9a4e64b9bd": 0.0 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/a9e36415-58b3-4e2c-b42a-757000d5e337.var b/.Variations/a9e36415-58b3-4e2c-b42a-757000d5e337.var index a4ac455d3a..fe37979a5f 100644 --- a/.Variations/a9e36415-58b3-4e2c-b42a-757000d5e337.var +++ b/.Variations/a9e36415-58b3-4e2c-b42a-757000d5e337.var @@ -1,3013 +1,4 @@ -{ - "Id": "a9e36415-58b3-4e2c-b42a-757000d5e337", - "Variations": [ - { - "Id": "4fb98ffc-f010-4233-9891-a9e8d17a1829", - "IsPreset": false, - "ActivationIndex": 6, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 0.46882638, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": -0.018195067, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 9.4, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.4419127, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -3.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 1.8702272, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.0042517944, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5149804, - "Z": 0.34126562, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.46968845, - "Z": 0.4013383, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - } - } - }, - { - "Id": "23314c25-8c8d-41de-9db7-177fdff46848", - "IsPreset": false, - "ActivationIndex": 40, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 0.6081597, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": -0.033195067, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.33677128, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": 282.0357, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5039037, - "Z": 0.27169368, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.30093023, - "Z": 0.30933613, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - } - } - }, - { - "Id": "4d646752-aabb-457a-911f-8791bf623ad6", - "IsPreset": false, - "ActivationIndex": 58, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "482fba6b-f92e-418c-a8f4-8da0f546c4a6": { - "X": 0.0, - "Y": -0.0029999972 - }, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5039037, - "Z": 0.27169368, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.30093023, - "Z": 0.30933613, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "675292bb-5b1d-4045-9072-c84ddd6e4614", - "IsPreset": false, - "ActivationIndex": 50, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "482fba6b-f92e-418c-a8f4-8da0f546c4a6": { - "X": 0.0, - "Y": -0.0029999972 - }, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5039037, - "Z": 0.27169368, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.30093023, - "Z": 0.30933613, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "58d81073-49ba-4a4b-a0ee-e476bcb19d47", - "IsPreset": false, - "ActivationIndex": 42, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5039037, - "Z": 0.27169368, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.30093023, - "Z": 0.30933613, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "16c7c6b2-e65d-48bb-9a93-81a3bce79e6d", - "IsPreset": false, - "ActivationIndex": 34, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 186.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.88, - "Y": 0.88, - "Z": 0.88, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.40765917, - "Z": 0.44097024, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4872961, - "Y": 0.51839715, - "Z": 0.5311489, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "fc03a818-1ee8-44d4-9c08-afd2365d51b2", - "IsPreset": false, - "ActivationIndex": 18, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 186.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.88, - "Y": 0.88, - "Z": 0.88, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.12843639, - "Z": 0.18873483, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4872961, - "Y": 0.51839715, - "Z": 0.5311489, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "d98e03a5-82d6-4126-866b-b3b2fe55b30e", - "IsPreset": false, - "ActivationIndex": 10, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 186.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "482fba6b-f92e-418c-a8f4-8da0f546c4a6": { - "X": 0.0, - "Y": -0.0079999985 - }, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.88, - "Y": 0.88, - "Z": 0.88, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.4015388, - "Z": 0.4354414, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4872961, - "Y": 0.51839715, - "Z": 0.5311489, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "8ee15dfd-743a-45fc-b8c0-ccba6872b253", - "IsPreset": false, - "ActivationIndex": 60, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 186.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.72727275, - "Y": 0.72727275, - "Z": 0.72727275, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.43708944, - "Y": 0.43809995, - "Z": 0.5, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.39093974, - "Y": 0.41687256, - "Z": 0.4275053, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.1999999 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - } - } - }, - { - "Id": "282135c2-e8b0-4f14-b9c1-93a00cd5a54e", - "IsPreset": false, - "ActivationIndex": 52, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 279.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.72727275, - "Y": 0.72727275, - "Z": 0.72727275, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.43708944, - "Y": 0.43809995, - "Z": 0.5, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.39093974, - "Y": 0.41687256, - "Z": 0.4275053, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.1999999 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - } - } - }, - { - "Id": "0789e8d3-56c9-4739-8351-0f336cf6445b", - "IsPreset": false, - "ActivationIndex": 44, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 279.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.72727275, - "Y": 0.72727275, - "Z": 0.72727275, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.43708944, - "Y": 0.43809995, - "Z": 0.5, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.39093974, - "Y": 0.41687256, - "Z": 0.4275053, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 2.8 - } - } - }, - { - "Id": "327e0229-7974-42a3-8e5e-5d2ddc1ef000", - "IsPreset": false, - "ActivationIndex": 36, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 279.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5289081, - "Y": 0.52986014, - "Z": 0.5881814, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.43870592, - "Y": 0.4678073, - "Z": 0.4797392, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 2.8 - } - } - }, - { - "Id": "da24957e-d196-42c4-9bc7-1fb72cdd0bfc", - "IsPreset": false, - "ActivationIndex": 20, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 279.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5289081, - "Y": 0.52986014, - "Z": 0.5881814, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4797392, - "Y": 0.23817807, - "Z": 0.30357224, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 2.8 - } - } - }, - { - "Id": "a0c99e6a-a31b-411d-b249-b1e3c3e7c350", - "IsPreset": false, - "ActivationIndex": 62, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 372.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5289081, - "Y": 0.52986014, - "Z": 0.5881814, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4797392, - "Y": 0.35177323, - "Z": 0.2675316, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 1 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.9100001 - } - } - }, - { - "Id": "06114ba1-8916-4d0e-a519-ed520482eb94", - "IsPreset": false, - "ActivationIndex": 46, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 372.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5289081, - "Y": 0.52986014, - "Z": 0.5881814, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4797392, - "Y": 0.35177323, - "Z": 0.2675316, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 1 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.9100001 - } - } - }, - { - "Id": "eaf3e257-29e6-4172-a75a-4edf1c237184", - "IsPreset": false, - "ActivationIndex": 14, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 372.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.1056676, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.8837733, - "Y": 0.8837733, - "Z": 0.8837733, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.500909, - "Y": 0.4115017, - "Z": 0.4455992, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4870585, - "Y": 0.5131578, - "Z": 0.5228597, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19411945, - "Y": 0.2731008, - "Z": 0.20332764, - "W": 0.007861063 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3062887 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 0 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.060058475 - } - } - }, - { - "Id": "c58ad4f2-e3b9-4c63-a245-ef199355fcda", - "IsPreset": false, - "ActivationIndex": 32, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 465.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 0.46882638, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": -0.033195067, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 10.3, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 4.4252462, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": 120.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5149804, - "Z": 0.34126562, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.46968845, - "Z": 0.4013383, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - } - } - }, - { - "Id": "5eef051e-e68e-483b-9f70-3d1137b2dc62", - "IsPreset": false, - "ActivationIndex": 0, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 465.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 0.6081597, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": -0.033195067, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.33677128, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": 282.0357, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5039037, - "Z": 0.27169368, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.30093023, - "Z": 0.30933613, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3062887 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 0 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - }, - "23a4c831-287f-4878-a65a-6a8a06ae3976": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 0 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.060058475 - } - } - }, - { - "Id": "0d7cb99a-a2d7-4641-8341-862ccaf043f6", - "IsPreset": false, - "ActivationIndex": 2, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 465.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.88, - "Y": 0.88, - "Z": 0.88, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.12843639, - "Z": 0.18873483, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4872961, - "Y": 0.51839715, - "Z": 0.5311489, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 0 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - }, - "23a4c831-287f-4878-a65a-6a8a06ae3976": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 0 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.060058475 - } - } - }, - { - "Id": "f8fa4d00-b1a2-4e7c-8cd7-03c11be6fc20", - "IsPreset": false, - "ActivationIndex": 1, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 465.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -4.2000003, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.88, - "Y": 0.88, - "Z": 0.88, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.12843639, - "Z": 0.18873483, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4872961, - "Y": 0.51839715, - "Z": 0.5311489, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.3 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 1 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - }, - "23a4c831-287f-4878-a65a-6a8a06ae3976": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 0 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.060058475 - } - } - }, - { - "Id": "f69ebdc9-b1ee-4178-9cba-9805f23d1359", - "IsPreset": false, - "ActivationIndex": 4, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 558.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 1.54, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": 0.063999996, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.19999999, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": -86.0, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": -1.2, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.38 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5289081, - "Y": 0.52986014, - "Z": 0.5881814, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.4797392, - "Y": 0.23817807, - "Z": 0.30357224, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.09754033, - "Y": 0.13722652, - "Z": 0.10216722, - "W": 0.25 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.5 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 2 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - }, - "23a4c831-287f-4878-a65a-6a8a06ae3976": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 1 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 2.8 - } - } - }, - { - "Id": "4347c0b8-0518-4b66-8729-a2f9fcde99c8", - "IsPreset": false, - "ActivationIndex": 57, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 558.0 - }, - "ParameterSetsForChildIds": { - "78215892-6dc1-454c-b46a-2950ba7fe3c3": { - "1d5207f0-132e-42e9-9b2b-171d092d6cac": 0.6081597, - "3ae3bc6a-5950-4f8b-b2c1-5247dfb9221c": -0.033195067, - "882acab3-7cb9-42e8-8f63-5382c83422c2": 0.96534115, - "95b99630-6d27-41d6-9e02-a3e905d023d7": 0.33677128, - "f1a53a46-fa5c-49af-9d53-0d68cfe1b33e": 5.8652463, - "fc1b2bc8-6756-4e78-a90b-8af691d85875": 282.0357, - "d2b9ef03-1641-4949-86ff-b71dc1fb3ad0": 1.0008872, - "b454ebb9-6b27-46b1-962e-15e658c8f6a2": 0.2835605, - "aedb3315-5061-4b68-8925-761d4d8c78b4": 0.00091846066, - "cbe45989-b239-491e-a2d8-83a42ab58b85": -0.0015625476, - "640de6a7-14ce-4c72-b78e-aa72f642b765": 2.4198031, - "9d210666-6b60-4193-9bfd-8a50c8973238": 0.37769055, - "37f312f0-949c-4a43-af92-786761b03d3b": 3.3274438, - "c3827e2e-2d15-475c-9b2f-03a861e97fc5": true - }, - "33fb0dab-461b-459e-8f7c-42753c4cec58": { - "4dc44a7b-fe7c-4807-aaaa-53fb553de017": { - "X": 0.7, - "Y": 0.5149804, - "Z": 0.34126562, - "W": 0.31000003 - }, - "be4dc864-a5f9-4356-91f9-58de8056a3a8": { - "X": 0.5, - "Y": 0.46968845, - "Z": 0.4013383, - "W": 0.506 - }, - "e8cc8a26-313e-4399-b800-901019bbaa78": { - "X": 0.5186364, - "Y": 0.5478363, - "Z": 0.5598086, - "W": 0.25 - }, - "423eb712-f7e3-4402-b841-324a9fc91c54": { - "X": 0.19725491, - "Y": 0.27751195, - "Z": 0.20661183, - "W": 0.0 - }, - "a0aaadb8-3b39-4a29-b04b-5043ec8bbf42": 0.88666666, - "e94da387-2c81-4ae0-a37e-3141e16c345d": 0.31666663 - }, - "2004e799-4527-465e-8496-c61604d2c6a6": { - "767ddbe0-202f-4d0b-9aa1-9a22d61a2d40": 1.2933333, - "0212bfb2-9f5f-4d60-aab0-3f9525bd7bfc": 0.3800001, - "4aa128ab-d0a8-42d5-800f-6992959bd0cf": 0.030000001, - "7f0c127b-ee60-44c8-8490-2d3599cde4a2": 45.333332, - "03298545-a5d6-44d5-bb7c-4747172d2667": { - "X": -0.002, - "Y": 0.015999999 - }, - "9d5e3055-c17e-4013-963d-e17c76b707c1": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "9c9e9e49-2f3a-4746-ac1f-c5fb1b3dd96b": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "d162a7e1-1906-45bc-a896-10ee2c2483fe": 0.070000015, - "f93db0c6-c5ed-40da-9677-0c284618f5bb": 2.0 - }, - "8877c032-ee6d-4d24-8652-ee44cc1f5ef8": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "3ac8ec9a-99a9-445b-9363-3fe865f7a87d": { - "7f66aa8d-fbdd-47d6-ba38-07e257e19401": 1.0, - "d3197979-b418-4182-b1c9-f3126b175f8d": 2.1366665, - "6d10c73c-37b8-443b-94d9-854b04027a3c": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - } - }, - "c3f4c2a6-88bd-4cdf-ae34-735039a32a84": { - "fa5bb047-7466-4d68-9977-7a86815ca0f2": 15.766667 - }, - "3e2d5e7d-6670-415a-8ab6-c38d3f040245": { - "abf3456d-35bc-49ec-9aa6-c5571fbb209a": { - "X": -0.25666666, - "Y": 0.0 - }, - "10d59d0f-a5a3-42e6-b874-345ab028978e": 2.75, - "8169be8f-cb35-4900-b462-f2139b412d59": 73.333336, - "5774969c-ef4d-482e-ab37-b3a84b09debb": true - }, - "e7e552b9-1d66-4463-934c-9944e52e0cc6": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 1.0 - }, - "3f44866a-766d-4a75-8f19-c960d01203bf": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 3.21 - }, - "33b8ee73-68e9-4ed1-8293-0c80227fea10": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 2 - }, - "4661b68c-bca2-48df-ae64-7819845335b0": { - "70dc133e-800a-4cd0-a159-2cbab4c322cb": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 0.58000004 - }, - "fc5f1d08-3997-4ba3-ac59-d86e4e501fb0": 3 - }, - "d7711f84-ca28-44a4-aff8-bdfac05d8540": { - "4515c98e-05bc-4186-8773-4d2b31a8c323": 0 - }, - "7060b926-fb9c-4c5b-8a15-0ede6a63f148": { - "87efd3c4-f2df-4996-924f-12c631bad8d8": 8001, - "7c681ee6-d071-4284-8585-1c3e03a089ea": false, - "6c15e743-9a70-47e7-a0a4-75636817e441": false - }, - "70a7ea94-0dc9-4268-b153-6efbd18aac56": { - "2f87e21a-a1bd-4e2a-948c-2fa35245998d": 2 - }, - "57fa6495-e1aa-4864-a0e3-0e46907b05db": { - "4424863b-b25c-449a-8ac9-16796617af7b": 0.32, - "b9a322a3-b85d-4e51-ad1c-17d61a6f5f5e": 0.292 - }, - "23a4c831-287f-4878-a65a-6a8a06ae3976": { - "29e289be-e735-4dd4-8826-5e434cc995fa": 0 - }, - "e9a7d938-af88-45ed-b570-e145405b0036": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.46 - } - } - } - ] +{ + "Id": "a9e36415-58b3-4e2c-b42a-757000d5e337", + "Variations": [] } \ No newline at end of file diff --git a/.Variations/d392d4af-4c78-4f4a-bc3f-4c54c8c73538.var b/.Variations/d392d4af-4c78-4f4a-bc3f-4c54c8c73538.var index 80df3de108..6d8248b08a 100644 --- a/.Variations/d392d4af-4c78-4f4a-bc3f-4c54c8c73538.var +++ b/.Variations/d392d4af-4c78-4f4a-bc3f-4c54c8c73538.var @@ -144,6 +144,21 @@ } } } + }, + { + "Id": "56fdecbd-1737-4934-b724-d1f260523213", + "IsPreset": true, + "ActivationIndex": 8, + "Title": "Wide", + "PosOnCanvas": { + "X": 163.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "57968725-0a45-44f9-a9a2-f74c10b728e8": 4.0 + } + } } ] } \ No newline at end of file diff --git a/.Variations/d9a71078-8296-4a07-b7de-250d4e2b95ac.var b/.Variations/d9a71078-8296-4a07-b7de-250d4e2b95ac.var index 4cb162399f..40f33a7558 100644 --- a/.Variations/d9a71078-8296-4a07-b7de-250d4e2b95ac.var +++ b/.Variations/d9a71078-8296-4a07-b7de-250d4e2b95ac.var @@ -7,7 +7,7 @@ "ActivationIndex": 1, "Title": "Alpha Mask", "PosOnCanvas": { - "X": 20.90538, + "X": 20.905426, "Y": -5.650284 }, "ParameterSetsForChildIds": { @@ -28,7 +28,7 @@ "ActivationIndex": 2, "Title": "Call 1 for Pony", "PosOnCanvas": { - "X": 183.90543, + "X": 183.90549, "Y": -5.650284 }, "ParameterSetsForChildIds": { @@ -181,72 +181,6 @@ "9756e240-6527-4cda-accd-e8096682b6bd": 0.76 } } - }, - { - "Id": "2b340cb5-9a9b-4c2d-8d83-e552904f7128", - "IsPreset": true, - "ActivationIndex": 7, - "Title": "sdf", - "PosOnCanvas": { - "X": 649.0, - "Y": 87.34972 - }, - "ParameterSetsForChildIds": { - "00000000-0000-0000-0000-000000000000": { - "387ce8fc-42c2-438d-bf52-144b5dfd8811": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "26a45300-c4d6-4e43-8550-37d2fa87799d": { - "X": 0.23923445, - "Y": 0.004153189, - "Z": 0.0, - "W": 1.0 - }, - "d09c7a75-d02d-421b-ba0f-17b345f523ec": { - "X": 1.0, - "Y": 0.4885525, - "Z": 0.6179481, - "W": 0.0 - }, - "9756e240-6527-4cda-accd-e8096682b6bd": 0.76 - } - } - }, - { - "Id": "5c732f0f-de85-4e6f-82d5-3c8856663e42", - "IsPreset": true, - "ActivationIndex": 8, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "00000000-0000-0000-0000-000000000000": { - "387ce8fc-42c2-438d-bf52-144b5dfd8811": { - "X": 1.0, - "Y": 1.0, - "Z": 1.0, - "W": 1.0 - }, - "26a45300-c4d6-4e43-8550-37d2fa87799d": { - "X": 0.23923445, - "Y": 0.004153189, - "Z": 0.0, - "W": 1.0 - }, - "d09c7a75-d02d-421b-ba0f-17b345f523ec": { - "X": 1.0, - "Y": 0.4885525, - "Z": 0.6179481, - "W": 0.0 - }, - "9756e240-6527-4cda-accd-e8096682b6bd": 0.76 - } - } } ] } \ No newline at end of file diff --git a/.Variations/dab61a12-9996-401e-9aa6-328dd6292beb.var b/.Variations/dab61a12-9996-401e-9aa6-328dd6292beb.var index 4c16e705b7..7878621580 100644 --- a/.Variations/dab61a12-9996-401e-9aa6-328dd6292beb.var +++ b/.Variations/dab61a12-9996-401e-9aa6-328dd6292beb.var @@ -1,98 +1,4 @@ { "Id": "dab61a12-9996-401e-9aa6-328dd6292beb", - "Variations": [ - { - "Id": "d14ed60f-2b17-4651-b2f1-a2bb81f43efd", - "IsPreset": false, - "ActivationIndex": 32, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "5299459b-7450-489c-a0e5-41ecfc2dd401", - "IsPreset": false, - "ActivationIndex": 24, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "47ec8204-71d5-4e3c-8ffa-068b9e2c7766", - "IsPreset": false, - "ActivationIndex": 33, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "e66f163a-d0b5-4591-aea8-f87c49233240", - "IsPreset": false, - "ActivationIndex": 25, - "Title": "untitled", - "PosOnCanvas": { - "X": 0.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "f29bfebc-f717-4881-b9bf-360dbe480094", - "IsPreset": false, - "ActivationIndex": 16, - "Title": "untitled", - "PosOnCanvas": { - "X": 163.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "4463101d-970e-4f0a-9a1b-77bdf2076a17", - "IsPreset": false, - "ActivationIndex": 34, - "Title": "untitled", - "PosOnCanvas": { - "X": 326.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": {} - } - }, - { - "Id": "a6260b15-7148-436f-a3aa-0a2d18bd70f0", - "IsPreset": false, - "ActivationIndex": 26, - "Title": "untitled", - "PosOnCanvas": { - "X": 489.0, - "Y": 93.0 - }, - "ParameterSetsForChildIds": { - "14f4b2c6-2d47-4097-9e9b-3ff13725d1a3": { - "7773837e-104a-4b3d-a41f-cadbd9249af2": 0.54 - } - } - } - ] + "Variations": [] } \ No newline at end of file diff --git a/.Variations/e1c294b5-1ea8-435e-a437-26d280d3c2f4.var b/.Variations/e1c294b5-1ea8-435e-a437-26d280d3c2f4.var index f19861acd8..452a183299 100644 --- a/.Variations/e1c294b5-1ea8-435e-a437-26d280d3c2f4.var +++ b/.Variations/e1c294b5-1ea8-435e-a437-26d280d3c2f4.var @@ -1,79 +1,105 @@ -{ - "Id": "e1c294b5-1ea8-435e-a437-26d280d3c2f4", - "Variations": [ - { - "Id": "8ecbf48c-e41b-45c2-bb56-1ca3bf58aa4d", - "IsPreset": true, - "ActivationIndex": 1, - "Title": "Normal", - "PosOnCanvas": { - "X": 163.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "00000000-0000-0000-0000-000000000000": { - "58c08101-ac16-4aed-aa84-259853734116": { - "X": -0.060000002, - "Y": -0.04000002, - "Z": -1.6000003 - }, - "6063bb2b-2255-4a0b-a222-7b8dd8397918": { - "X": 1.0, - "Y": 0.84360933, - "Z": 0.81483614, - "W": 1.0 - }, - "2f365f2a-8a2e-472c-af15-9352b54e2009": { - "X": 0.9261255, - "Y": 0.9418822, - "Z": 1.0, - "W": 1.0 - }, - "500549e0-aa60-4555-b82a-a829568959ff": 0.4, - "b9ca7291-1f78-47e2-8ba9-35ccb282833c": 0.61, - "c59b6588-9e39-49ed-99b7-632e5f2b3bf4": 0.25, - "59568136-2903-4fd5-a504-8a6308a2a2dc": 40, - "2e487d56-cc02-42d6-978e-aeb776516118": 9, - "9529d9b2-40ca-4f30-9142-1338dc4e07ff": 0.08 - } - } - }, - { - "Id": "d8e5e902-628c-4786-9a48-b16efb80f360", - "IsPreset": true, - "ActivationIndex": 2, - "Title": "Disturbingly Incorrect", - "PosOnCanvas": { - "X": 326.0, - "Y": 0.0 - }, - "ParameterSetsForChildIds": { - "00000000-0000-0000-0000-000000000000": { - "58c08101-ac16-4aed-aa84-259853734116": { - "X": -0.060000002, - "Y": -0.04000002, - "Z": -1.6000003 - }, - "6063bb2b-2255-4a0b-a222-7b8dd8397918": { - "X": 0.9791917, - "Y": 0.9879676, - "Z": 1.0, - "W": 1.0 - }, - "2f365f2a-8a2e-472c-af15-9352b54e2009": { - "X": 0.0, - "Y": 0.0, - "Z": 0.0, - "W": 1.0 - }, - "500549e0-aa60-4555-b82a-a829568959ff": 0.59, - "b9ca7291-1f78-47e2-8ba9-35ccb282833c": 0.5, - "c59b6588-9e39-49ed-99b7-632e5f2b3bf4": 1.0, - "59568136-2903-4fd5-a504-8a6308a2a2dc": 40, - "2e487d56-cc02-42d6-978e-aeb776516118": 10, - "9529d9b2-40ca-4f30-9142-1338dc4e07ff": 0.08 - } - } - } - ] +{ + "Id": "e1c294b5-1ea8-435e-a437-26d280d3c2f4", + "Variations": [ + { + "Id": "8ecbf48c-e41b-45c2-bb56-1ca3bf58aa4d", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Normal", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "58c08101-ac16-4aed-aa84-259853734116": { + "X": -0.060000002, + "Y": -0.04000002, + "Z": -1.6000003 + }, + "6063bb2b-2255-4a0b-a222-7b8dd8397918": { + "X": 1.0, + "Y": 0.84360933, + "Z": 0.81483614, + "W": 1.0 + }, + "2f365f2a-8a2e-472c-af15-9352b54e2009": { + "X": 0.9261255, + "Y": 0.9418822, + "Z": 1.0, + "W": 1.0 + }, + "500549e0-aa60-4555-b82a-a829568959ff": 0.4, + "b9ca7291-1f78-47e2-8ba9-35ccb282833c": 0.61, + "c59b6588-9e39-49ed-99b7-632e5f2b3bf4": 0.25, + "59568136-2903-4fd5-a504-8a6308a2a2dc": 40, + "2e487d56-cc02-42d6-978e-aeb776516118": 9, + "9529d9b2-40ca-4f30-9142-1338dc4e07ff": 0.08 + } + } + }, + { + "Id": "d8e5e902-628c-4786-9a48-b16efb80f360", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Disturbingly Incorrect", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "58c08101-ac16-4aed-aa84-259853734116": { + "X": -0.060000002, + "Y": -0.04000002, + "Z": -1.6000003 + }, + "6063bb2b-2255-4a0b-a222-7b8dd8397918": { + "X": 0.9791917, + "Y": 0.9879676, + "Z": 1.0, + "W": 1.0 + }, + "2f365f2a-8a2e-472c-af15-9352b54e2009": { + "X": 0.0, + "Y": 0.0, + "Z": 0.0, + "W": 1.0 + }, + "500549e0-aa60-4555-b82a-a829568959ff": 0.59, + "b9ca7291-1f78-47e2-8ba9-35ccb282833c": 0.5, + "c59b6588-9e39-49ed-99b7-632e5f2b3bf4": 1.0, + "59568136-2903-4fd5-a504-8a6308a2a2dc": 40, + "2e487d56-cc02-42d6-978e-aeb776516118": 10, + "9529d9b2-40ca-4f30-9142-1338dc4e07ff": 0.08 + } + } + }, + { + "Id": "b2a54296-0ed7-45b1-a921-4adafd99d0c2", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Default2", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "2f365f2a-8a2e-472c-af15-9352b54e2009": { + "X": 0.8995215, + "Y": 0.8995215, + "Z": 0.8995215, + "W": 1.0 + }, + "500549e0-aa60-4555-b82a-a829568959ff": 2.13, + "b9ca7291-1f78-47e2-8ba9-35ccb282833c": 0.22, + "c59b6588-9e39-49ed-99b7-632e5f2b3bf4": 0.35, + "2e487d56-cc02-42d6-978e-aeb776516118": 8, + "9529d9b2-40ca-4f30-9142-1338dc4e07ff": 0.077999994, + "ea737eeb-e936-48c0-aaa7-8247fea95228": 0.5 + } + } + } + ] } \ No newline at end of file diff --git a/.Variations/e44ae9b6-cd56-4224-8a5d-118eda4cd3f4.var b/.Variations/e44ae9b6-cd56-4224-8a5d-118eda4cd3f4.var new file mode 100644 index 0000000000..5ddd2b8f70 --- /dev/null +++ b/.Variations/e44ae9b6-cd56-4224-8a5d-118eda4cd3f4.var @@ -0,0 +1,53 @@ +{ + "Id": "e44ae9b6-cd56-4224-8a5d-118eda4cd3f4", + "Variations": [ + { + "Id": "0488f2b1-df03-4b4a-8315-3fc0ed8f131b", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Default", + "PosOnCanvas": { + "X": 0.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "c6bdbb07-6996-4e5b-a058-37c9cbeca6fe": false + } + } + }, + { + "Id": "054e59e1-f77a-4c2b-8dea-866704029440", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Some velocity and drag", + "PosOnCanvas": { + "X": 162.99998, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "e9f068dd-9bd9-4b1c-9122-f78df0ec18b9": true, + "5a61994e-42c7-47e7-b0a5-5beb48f4a34b": 0.012 + } + } + }, + { + "Id": "10ca7a0d-b9e5-43e1-9220-9480aa8a6b34", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Aging", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "e9f068dd-9bd9-4b1c-9122-f78df0ec18b9": true, + "5a61994e-42c7-47e7-b0a5-5beb48f4a34b": 0.012, + "a7350ba8-08be-4afc-92f1-d223ee9bcbeb": 1 + } + } + } + ] +} \ No newline at end of file diff --git a/.Variations/ea7b8491-2f8e-4add-b0b1-fd068ccfed0d.var b/.Variations/ea7b8491-2f8e-4add-b0b1-fd068ccfed0d.var index 87c8bd35bc..6aaeb0eb07 100644 --- a/.Variations/ea7b8491-2f8e-4add-b0b1-fd068ccfed0d.var +++ b/.Variations/ea7b8491-2f8e-4add-b0b1-fd068ccfed0d.var @@ -22,8 +22,8 @@ "ActivationIndex": 2, "Title": "Endless", "PosOnCanvas": { - "X": 326.0, - "Y": 0.0 + "X": 0.0, + "Y": 93.0 }, "ParameterSetsForChildIds": { "00000000-0000-0000-0000-000000000000": { @@ -37,8 +37,8 @@ "ActivationIndex": 3, "Title": "Wave", "PosOnCanvas": { - "X": 489.0, - "Y": 0.0 + "X": 163.0, + "Y": 93.0 }, "ParameterSetsForChildIds": { "00000000-0000-0000-0000-000000000000": { @@ -76,6 +76,21 @@ "79917ef7-64ca-4825-9c6a-c9b2a7f6ff86": 15.0 } } + }, + { + "Id": "c12d9d4d-713c-4075-a653-76d5a25187f9", + "IsPreset": true, + "ActivationIndex": 6, + "Title": "Sine", + "PosOnCanvas": { + "X": 326.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "4cf5d20b-7335-4584-b246-c260ac5cdf4f": 7 + } + } } ] } \ No newline at end of file diff --git a/.Variations/ecbb40c4-aef4-49a8-ac89-e82c3a09862f.var b/.Variations/ecbb40c4-aef4-49a8-ac89-e82c3a09862f.var new file mode 100644 index 0000000000..c9adcd54db --- /dev/null +++ b/.Variations/ecbb40c4-aef4-49a8-ac89-e82c3a09862f.var @@ -0,0 +1,143 @@ +{ + "Id": "ecbb40c4-aef4-49a8-ac89-e82c3a09862f", + "Variations": [ + { + "Id": "60765230-7ea9-4725-b7ae-a6bf4dabf7e8", + "IsPreset": true, + "ActivationIndex": 1, + "Title": "Default", + "PosOnCanvas": { + "X": 163.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": {} + } + }, + { + "Id": "bca84101-f58d-4fb7-8eb8-f35d9e0e75bd", + "IsPreset": true, + "ActivationIndex": 2, + "Title": "Few long ones", + "PosOnCanvas": { + "X": 326.0, + "Y": 0.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "c643292c-5612-408a-9fd6-ce31e4de3f56": 0.25, + "68e16fd7-fabf-446e-9553-a737422c026b": 28.7, + "8c1d41ff-02e8-481b-a21a-56d1c519d920": 0.9 + } + } + }, + { + "Id": "59228dbe-c991-426a-8c5a-f2e3075b9b7d", + "IsPreset": true, + "ActivationIndex": 3, + "Title": "Suptle glints", + "PosOnCanvas": { + "X": 0.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "87148268-6d28-4d71-a2b5-b1ec0fb66685": { + "X": 1.0, + "Y": 0.9745251, + "Z": 0.7087233, + "W": 1.0 + }, + "c643292c-5612-408a-9fd6-ce31e4de3f56": 0.1, + "68e16fd7-fabf-446e-9553-a737422c026b": 10.0, + "8c1d41ff-02e8-481b-a21a-56d1c519d920": 0.75, + "dd0e21b8-91a6-4853-9907-e0f675a05a5d": 8, + "6bc1a296-1a17-44a2-ba41-2c51c192090c": { + "X": 0.5610631, + "Y": 0.61537164, + "Z": 0.67942584, + "W": 1.0 + } + } + } + }, + { + "Id": "792d1b30-0a32-4aaa-8c3a-db7d5bb41bc8", + "IsPreset": true, + "ActivationIndex": 4, + "Title": "Softporn", + "PosOnCanvas": { + "X": 163.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "c643292c-5612-408a-9fd6-ce31e4de3f56": 0.05, + "68e16fd7-fabf-446e-9553-a737422c026b": 7.12, + "8c1d41ff-02e8-481b-a21a-56d1c519d920": 0.26, + "dd0e21b8-91a6-4853-9907-e0f675a05a5d": 8, + "6bc1a296-1a17-44a2-ba41-2c51c192090c": { + "X": 0.39999998, + "Y": 0.39999998, + "Z": 0.39999998, + "W": 1.0 + } + } + } + }, + { + "Id": "603bf59a-f51c-4aa1-89b0-37f8e23ca1dd", + "IsPreset": true, + "ActivationIndex": 5, + "Title": "What the Frog", + "PosOnCanvas": { + "X": 326.0, + "Y": 93.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "c643292c-5612-408a-9fd6-ce31e4de3f56": 0.05, + "68e16fd7-fabf-446e-9553-a737422c026b": 7.12, + "8c1d41ff-02e8-481b-a21a-56d1c519d920": 0.26, + "dd0e21b8-91a6-4853-9907-e0f675a05a5d": 4, + "6bc1a296-1a17-44a2-ba41-2c51c192090c": { + "X": 0.39999998, + "Y": 0.39999998, + "Z": 0.39999998, + "W": 1.0 + } + } + } + }, + { + "Id": "4581a380-4acf-49b4-b086-7469495bcf08", + "IsPreset": true, + "ActivationIndex": 6, + "Title": "Mom, I broke it.", + "PosOnCanvas": { + "X": 0.0, + "Y": 186.0 + }, + "ParameterSetsForChildIds": { + "00000000-0000-0000-0000-000000000000": { + "87148268-6d28-4d71-a2b5-b1ec0fb66685": { + "X": 0.6540072, + "Y": 1.0, + "Z": 0.9967923, + "W": 1.0 + }, + "c643292c-5612-408a-9fd6-ce31e4de3f56": 0.05, + "68e16fd7-fabf-446e-9553-a737422c026b": 7.12, + "8c1d41ff-02e8-481b-a21a-56d1c519d920": 0.5, + "dd0e21b8-91a6-4853-9907-e0f675a05a5d": 4, + "6bc1a296-1a17-44a2-ba41-2c51c192090c": { + "X": 0.39999998, + "Y": 0.31164882, + "Z": 0.31053942, + "W": 1.0 + } + } + } + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 81ff60ba4a..edfbd4fcf5 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,9 @@ bld/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ +# VsCode local configurations +.vscode/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* diff --git a/Core/Core.csproj b/Core/Core.csproj index bc78b5f14f..550c293f3a 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -1,28 +1,28 @@ - - - - net6.0-windows - true - None - T3.Core - - - - - - - - - - - - - - - - - - - - - + + + + net6.0-windows + true + None + T3.Core + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/DataTypes/LegacyParticleSystem.cs b/Core/DataTypes/LegacyParticleSystem.cs new file mode 100644 index 0000000000..6ee3a2ed1c --- /dev/null +++ b/Core/DataTypes/LegacyParticleSystem.cs @@ -0,0 +1,116 @@ +using System.Linq; +using SharpDX; +using SharpDX.D3DCompiler; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using T3.Core.Logging; +using T3.Core.Resource; + +namespace T3.Core.DataTypes +{ + public class LegacyParticleSystem + { + public Buffer ParticleBuffer; + public UnorderedAccessView ParticleBufferUav; + public ShaderResourceView ParticleBufferSrv; + + public Buffer DeadParticleIndices; + public UnorderedAccessView DeadParticleIndicesUav; + + public Buffer AliveParticleIndices; + public UnorderedAccessView AliveParticleIndicesUav; + public ShaderResourceView AliveParticleIndicesSrv; + + public Buffer IndirectArgsBuffer; + public UnorderedAccessView IndirectArgsBufferUav; + + public Buffer ParticleCountConstBuffer; + + public int MaxCount { get; set; } = 20480; + public readonly int ParticleSizeInBytes = 80; + private uint _initDeadListShaderResId = ResourceManager.NullResource; + public int ParticleSystemSizeInBytes => MaxCount * ParticleSizeInBytes; + + public void Init() + { + if (_initDeadListShaderResId == ResourceManager.NullResource) + { + string sourcePath = @"Resources\lib\particles\particle-dead-list-init.hlsl"; + string entryPoint = "main"; + string debugName = "particle-dead-list-init"; + var resourceManager = ResourceManager.Instance(); + resourceManager.CreateComputeShaderFromFile(out _initDeadListShaderResId, sourcePath, entryPoint, debugName, null); + } + + InitParticleBufferAndViews(); + InitDeadParticleIndices(); + InitAliveParticleIndices(); + InitIndirectArgBuffer(); + InitParticleCountConstBuffer(); + } + + private void InitParticleBufferAndViews() + { + ResourceManager.Instance(); + int stride = ParticleSizeInBytes; + var bufferData = Enumerable.Repeat(-10.0f, MaxCount * (stride / 4)).ToArray(); // init with negative lifetime other values doesn't matter + ResourceManager.SetupStructuredBuffer(bufferData, stride * MaxCount, stride, ref ParticleBuffer); + ResourceManager.CreateStructuredBufferUav(ParticleBuffer, UnorderedAccessViewBufferFlags.None, ref ParticleBufferUav); + ResourceManager.CreateStructuredBufferSrv(ParticleBuffer, ref ParticleBufferSrv); + } + + private const int ParticleIndexSizeInBytes = 8; + + private void InitDeadParticleIndices() + { + // init the buffer + var resourceManager = ResourceManager.Instance(); + ResourceManager.SetupStructuredBuffer(ParticleIndexSizeInBytes*MaxCount, ParticleIndexSizeInBytes, ref DeadParticleIndices); + ResourceManager.CreateStructuredBufferUav(DeadParticleIndices, UnorderedAccessViewBufferFlags.Append, ref DeadParticleIndicesUav); + + // init counter of the dead list buffer (must be done due to uav binding) + ComputeShader deadListInitShader = resourceManager.GetComputeShader(_initDeadListShaderResId); + var device = ResourceManager.Device; + var deviceContext = device.ImmediateContext; + var csStage = deviceContext.ComputeShader; + var prevShader = csStage.Get(); + var prevUavs = csStage.GetUnorderedAccessViews(0, 1); + + // set and call the init shader + var reflectedShader = new ShaderReflection(resourceManager.GetComputeShaderBytecode(_initDeadListShaderResId)); + reflectedShader.GetThreadGroupSize(out int x, out int y, out int z); + + csStage.Set(deadListInitShader); + csStage.SetUnorderedAccessView(0, DeadParticleIndicesUav, 0); + int dispatchCount = MaxCount / (x > 0 ? x : 1); + Log.Info($"particle system: maxcount {MaxCount} dispatchCount: {dispatchCount} *64: {dispatchCount*64}"); + deviceContext.Dispatch(dispatchCount, 1, 1); + + // restore prev setup + csStage.SetUnorderedAccessView(0, prevUavs[0]); + csStage.Set(prevShader); + } + + private void InitAliveParticleIndices() + { + var resourceManager = ResourceManager.Instance(); + ResourceManager.SetupStructuredBuffer(ParticleIndexSizeInBytes*MaxCount, ParticleIndexSizeInBytes, ref AliveParticleIndices); + ResourceManager.CreateStructuredBufferUav(AliveParticleIndices, UnorderedAccessViewBufferFlags.Counter, ref AliveParticleIndicesUav); + ResourceManager.CreateStructuredBufferSrv(AliveParticleIndices, ref AliveParticleIndicesSrv); + } + + private void InitIndirectArgBuffer() + { + var resourceManager = ResourceManager.Instance(); + int sizeInBytes = 16; + ResourceManager.SetupIndirectBuffer(sizeInBytes, ref IndirectArgsBuffer); + ResourceManager.CreateBufferUav(IndirectArgsBuffer, Format.R32_UInt, ref IndirectArgsBufferUav); + } + + private void InitParticleCountConstBuffer() + { + ResourceManager.SetupConstBuffer(Vector4.Zero, ref ParticleCountConstBuffer); + ParticleCountConstBuffer.DebugName = "ParticleCountConstBuffer"; + } + } +} \ No newline at end of file diff --git a/Core/DataTypes/MeshBuffers.cs b/Core/DataTypes/MeshBuffers.cs index 4d5211e1aa..054cf2d149 100644 --- a/Core/DataTypes/MeshBuffers.cs +++ b/Core/DataTypes/MeshBuffers.cs @@ -7,5 +7,20 @@ public class MeshBuffers { public BufferWithViews VertexBuffer; public BufferWithViews IndicesBuffer; + + public override string ToString() + { + if(VertexBuffer?.Srv == null && IndicesBuffer?.Srv == null) + return "Undefined"; + + var vertexCount = VertexBuffer?.Srv != null + ? VertexBuffer.Srv.Description.Buffer.ElementCount + :0 ; + var indicesCount = IndicesBuffer?.Srv != null + ? IndicesBuffer.Srv.Description.Buffer.ElementCount + :0 ; + + return $"{vertexCount} vertices {indicesCount} faces"; + } } } \ No newline at end of file diff --git a/Core/DataTypes/ParticleSystem.cs b/Core/DataTypes/ParticleSystem.cs index 2f3ab87b14..aee4992378 100644 --- a/Core/DataTypes/ParticleSystem.cs +++ b/Core/DataTypes/ParticleSystem.cs @@ -1,116 +1,50 @@ -using System.Linq; -using SharpDX; -using SharpDX.D3DCompiler; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using T3.Core.Logging; -using T3.Core.Resource; - -namespace T3.Core.DataTypes -{ - public class ParticleSystem - { - public Buffer ParticleBuffer; - public UnorderedAccessView ParticleBufferUav; - public ShaderResourceView ParticleBufferSrv; - - public Buffer DeadParticleIndices; - public UnorderedAccessView DeadParticleIndicesUav; - - public Buffer AliveParticleIndices; - public UnorderedAccessView AliveParticleIndicesUav; - public ShaderResourceView AliveParticleIndicesSrv; - - public Buffer IndirectArgsBuffer; - public UnorderedAccessView IndirectArgsBufferUav; - - public Buffer ParticleCountConstBuffer; - - public int MaxCount { get; set; } = 20480; - public readonly int ParticleSizeInBytes = 80; - private uint _initDeadListShaderResId = ResourceManager.NullResource; - public int ParticleSystemSizeInBytes => MaxCount * ParticleSizeInBytes; - - public void Init() - { - if (_initDeadListShaderResId == ResourceManager.NullResource) - { - string sourcePath = @"Resources\lib\particles\particle-dead-list-init.hlsl"; - string entryPoint = "main"; - string debugName = "particle-dead-list-init"; - var resourceManager = ResourceManager.Instance(); - resourceManager.CreateComputeShaderFromFile(out _initDeadListShaderResId, sourcePath, entryPoint, debugName, null); - } - - InitParticleBufferAndViews(); - InitDeadParticleIndices(); - InitAliveParticleIndices(); - InitIndirectArgBuffer(); - InitParticleCountConstBuffer(); - } - - private void InitParticleBufferAndViews() - { - ResourceManager.Instance(); - int stride = ParticleSizeInBytes; - var bufferData = Enumerable.Repeat(-10.0f, MaxCount * (stride / 4)).ToArray(); // init with negative lifetime other values doesn't matter - ResourceManager.SetupStructuredBuffer(bufferData, stride * MaxCount, stride, ref ParticleBuffer); - ResourceManager.CreateStructuredBufferUav(ParticleBuffer, UnorderedAccessViewBufferFlags.None, ref ParticleBufferUav); - ResourceManager.CreateStructuredBufferSrv(ParticleBuffer, ref ParticleBufferSrv); - } - - private const int ParticleIndexSizeInBytes = 8; - - private void InitDeadParticleIndices() - { - // init the buffer - var resourceManager = ResourceManager.Instance(); - ResourceManager.SetupStructuredBuffer(ParticleIndexSizeInBytes*MaxCount, ParticleIndexSizeInBytes, ref DeadParticleIndices); - ResourceManager.CreateStructuredBufferUav(DeadParticleIndices, UnorderedAccessViewBufferFlags.Append, ref DeadParticleIndicesUav); - - // init counter of the dead list buffer (must be done due to uav binding) - ComputeShader deadListInitShader = resourceManager.GetComputeShader(_initDeadListShaderResId); - var device = ResourceManager.Device; - var deviceContext = device.ImmediateContext; - var csStage = deviceContext.ComputeShader; - var prevShader = csStage.Get(); - var prevUavs = csStage.GetUnorderedAccessViews(0, 1); - - // set and call the init shader - var reflectedShader = new ShaderReflection(resourceManager.GetComputeShaderBytecode(_initDeadListShaderResId)); - reflectedShader.GetThreadGroupSize(out int x, out int y, out int z); - - csStage.Set(deadListInitShader); - csStage.SetUnorderedAccessView(0, DeadParticleIndicesUav, 0); - int dispatchCount = MaxCount / (x > 0 ? x : 1); - Log.Info($"particle system: maxcount {MaxCount} dispatchCount: {dispatchCount} *64: {dispatchCount*64}"); - deviceContext.Dispatch(dispatchCount, 1, 1); - - // restore prev setup - csStage.SetUnorderedAccessView(0, prevUavs[0]); - csStage.Set(prevShader); - } - - private void InitAliveParticleIndices() - { - var resourceManager = ResourceManager.Instance(); - ResourceManager.SetupStructuredBuffer(ParticleIndexSizeInBytes*MaxCount, ParticleIndexSizeInBytes, ref AliveParticleIndices); - ResourceManager.CreateStructuredBufferUav(AliveParticleIndices, UnorderedAccessViewBufferFlags.Counter, ref AliveParticleIndicesUav); - ResourceManager.CreateStructuredBufferSrv(AliveParticleIndices, ref AliveParticleIndicesSrv); - } - - private void InitIndirectArgBuffer() - { - var resourceManager = ResourceManager.Instance(); - int sizeInBytes = 16; - ResourceManager.SetupIndirectBuffer(sizeInBytes, ref IndirectArgsBuffer); - ResourceManager.CreateBufferUav(IndirectArgsBuffer, Format.R32_UInt, ref IndirectArgsBufferUav); - } - - private void InitParticleCountConstBuffer() - { - ResourceManager.SetupConstBuffer(Vector4.Zero, ref ParticleCountConstBuffer); - ParticleCountConstBuffer.DebugName = "ParticleCountConstBuffer"; - } - } +using System.Numerics; +using System.Runtime.InteropServices; + +namespace T3.Core.DataTypes +{ + /// + /// Combines buffers required for mesh rendering + /// + public class ParticleSystem + { + public BufferWithViews ParticleBuffer; + public float SpeedFactor; + public float InitializeVelocityFactor; + } + + /// + /// Hold additional point information require for particle simulations. + /// + [StructLayout(LayoutKind.Explicit, Size = 16 * 4)] + public struct ParticlePoint + { + [FieldOffset(0)] + public Vector3 Position; + + [FieldOffset(3*4)] + public float BirthTime; + + [FieldOffset(4*4)] + public Vector3 Velocity; + + [FieldOffset(7*4)] + public float Radius; + + [FieldOffset(8*4)] + public Quaternion Rotation; + + [FieldOffset(12*4)] + public Vector4 __extra; + + public static ParticlePoint Separator() + { + return new ParticlePoint + { + Velocity = Vector3.Zero, + BirthTime = 0, + Radius = 1, + }; + } + } } \ No newline at end of file diff --git a/Core/IO/ProjectSettings.cs b/Core/IO/ProjectSettings.cs index 88bd69a3ef..7f47c75af1 100644 --- a/Core/IO/ProjectSettings.cs +++ b/Core/IO/ProjectSettings.cs @@ -18,6 +18,7 @@ public class ConfigData public bool WindowedMode = false; public string LimitMidiDeviceCapture = null; + public bool EnableMidiSnapshotIndication = false; } } } \ No newline at end of file diff --git a/Core/Model/Model.TypeRegistration.cs b/Core/Model/Model.TypeRegistration.cs index 5ec1ee9b51..750267c566 100644 --- a/Core/Model/Model.TypeRegistration.cs +++ b/Core/Model/Model.TypeRegistration.cs @@ -1,471 +1,474 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using SharpDX; -using SharpDX.Direct3D; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using SharpDX.Mathematics.Interop; -using T3.Core.Animation; -using T3.Core.DataTypes; -using T3.Core.DataTypes.DataSet; -using T3.Core.Operator.Slots; -using T3.Core.Resource; -using Buffer = SharpDX.Direct3D11.Buffer; -using Point = T3.Core.DataTypes.Point; -using Vector4 = System.Numerics.Vector4; - -namespace T3.Core.Model; - -public static class JsonToTypeValueConverters -{ - public static Dictionary> Entries { get; } = new(); -} - -public static class TypeValueToJsonConverters -{ - public static Dictionary> Entries { get; } = new(); -} - -public static class InputValueCreators -{ - public static Dictionary> Entries { get; } = new(); -} - -public static class TypeNameRegistry -{ - public static Dictionary Entries { get; } = new(20); -} - -public partial class SymbolData -{ - static SymbolData() - { - RegisterTypes(); - } - - private static void RegisterTypes() - { - // generic enum value from json function, must be local function - object JsonToEnumValue(JToken jsonToken) where T : struct // todo: use 7.3 and replace with enum - { - var value = jsonToken.Value(); - - if (Enum.TryParse(value, out T enumValue)) - { - return enumValue; - } - - return null; - } - - InputValue InputDefaultValueCreator() => new InputValue(); - - // build-in default types - RegisterType(typeof(float), "float", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue((float)obj), - jsonToken => jsonToken.Value()); - RegisterType(typeof(int), "int", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue((int)obj), - jsonToken => jsonToken.Value()); - RegisterType(typeof(bool), "bool", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue((bool)obj), - jsonToken => jsonToken.Value()); - RegisterType(typeof(double), "double", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue((double)obj), - jsonToken => jsonToken.Value()); - - RegisterType(typeof(string), "string", - () => new InputValue(string.Empty), - (writer, value) => writer.WriteValue((string)value), - jsonToken => jsonToken.Value()); - - // system types - RegisterType(typeof(System.Numerics.Vector2), "Vector2", - InputDefaultValueCreator, - (writer, obj) => - { - var vec = (System.Numerics.Vector2)obj; - writer.WriteStartObject(); - writer.WriteValue("X", vec.X); - writer.WriteValue("Y", vec.Y); - writer.WriteEndObject(); - }, - jsonToken => - { - float x = jsonToken["X"].Value(); - float y = jsonToken["Y"].Value(); - return new System.Numerics.Vector2(x, y); - }); - RegisterType(typeof(System.Numerics.Vector3), "Vector3", - InputDefaultValueCreator, - (writer, obj) => - { - var vec = (System.Numerics.Vector3)obj; - writer.WriteStartObject(); - writer.WriteValue("X", vec.X); - writer.WriteValue("Y", vec.Y); - writer.WriteValue("Z", vec.Z); - writer.WriteEndObject(); - }, - jsonToken => - { - float x = jsonToken["X"].Value(); - float y = jsonToken["Y"].Value(); - float z = jsonToken["Z"].Value(); - return new System.Numerics.Vector3(x, y, z); - }); - RegisterType(typeof(System.Numerics.Vector4), "Vector4", - () => new InputValue(new Vector4(1.0f, 1.0f, 1.0f, 1.0f)), - (writer, obj) => - { - var vec = (Vector4)obj; - writer.WriteStartObject(); - writer.WriteValue("X", vec.X); - writer.WriteValue("Y", vec.Y); - writer.WriteValue("Z", vec.Z); - writer.WriteValue("W", vec.W); - writer.WriteEndObject(); - }, - jsonToken => - { - float x = jsonToken["X"].Value(); - float y = jsonToken["Y"].Value(); - float z = jsonToken["Z"].Value(); - float w = jsonToken["W"].Value(); - return new Vector4(x, y, z, w); - }); - RegisterType(typeof(System.Numerics.Quaternion), "Quaternion", - () => new InputValue(System.Numerics.Quaternion.Identity), - (writer, obj) => - { - var quaternion = (System.Numerics.Quaternion)obj; - writer.WriteStartObject(); - writer.WriteValue("X", quaternion.X); - writer.WriteValue("Y", quaternion.Y); - writer.WriteValue("Z", quaternion.Z); - writer.WriteValue("W", quaternion.W); - writer.WriteEndObject(); - }, - jsonToken => - { - float x = jsonToken["X"].Value(); - float y = jsonToken["Y"].Value(); - float z = jsonToken["Z"].Value(); - float w = jsonToken["W"].Value(); - return new System.Numerics.Quaternion(x, y, z, w); - }); - - RegisterType(typeof(System.Collections.Generic.List), "List", - () => new InputValue>(new List()), - (writer, obj) => - { - var list = (List)obj; - writer.WriteStartObject(); - writer.WritePropertyName("Values"); - writer.WriteStartArray(); - list.ForEach(writer.WriteValue); - writer.WriteEndArray(); - writer.WriteEndObject(); - }, - jsonToken => - { - var entries = jsonToken["Values"]; - var list = new List(entries.Count()); - list.AddRange(entries.Select(entry => entry.Value())); - - return list; - }); - RegisterType(typeof(System.Collections.Generic.List), "List", - () => new InputValue>(new List()), - (writer, obj) => - { - var list = (List)obj; - writer.WriteStartObject(); - writer.WritePropertyName("Values"); - writer.WriteStartArray(); - list.ForEach(writer.WriteValue); - writer.WriteEndArray(); - writer.WriteEndObject(); - }, - jsonToken => - { - var entries = jsonToken["Values"]; - var list = new List(entries.Count()); - list.AddRange(entries.Select(entry => entry.Value())); - return list; - }); - - - RegisterType(typeof(System.Text.StringBuilder), "StringBuilder", - () => new InputValue(new StringBuilder())); - - RegisterType(typeof(DateTime), "DateTime", - () => new InputValue(new DateTime())); - - // t3 core types - RegisterType(typeof(BufferWithViews), "BufferWithViews", - () => new InputValue(null)); - - RegisterType(typeof(Command), "Command", - () => new InputValue(null)); - - RegisterType(typeof(Curve), "Curve", - InputDefaultValueCreator, - (writer, obj) => - { - Curve curve = (Curve)obj; - writer.WriteStartObject(); - curve?.Write(writer); - writer.WriteEndObject(); - }, - jsonToken => - { - Curve curve = new Curve(); - if (jsonToken == null || !jsonToken.HasValues) - { - curve.AddOrUpdateV(0, new VDefinition() { Value = 0 }); - curve.AddOrUpdateV(1, new VDefinition() { Value = 1 }); - } - else - { - curve.Read(jsonToken); - } - - return curve; - }); - - - RegisterType(typeof(DataTypes.Gradient), "Gradient", - InputDefaultValueCreator, - (writer, obj) => - { - Gradient gradient = (Gradient)obj; - writer.WriteStartObject(); - gradient?.Write(writer); - writer.WriteEndObject(); - }, - jsonToken => - { - Gradient gradient = new Gradient(); - if (jsonToken == null || !jsonToken.HasValues) - { - gradient = new Gradient(); - } - else - { - gradient.Read(jsonToken); - } - - return gradient; - }); - RegisterType(typeof(ParticleSystem), "ParticleSystem", - () => new InputValue(null)); - - RegisterType(typeof(T3.Core.Operator.GizmoVisibility), "GizmoVisibility", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - - RegisterType(typeof(Point[]), "Point", - () => new InputValue()); - RegisterType(typeof(RenderTargetReference), "RenderTargetRef", - () => new InputValue()); - RegisterType(typeof(Object), "Object", - () => new InputValue()); - RegisterType(typeof(StructuredList), "StructuredList", - () => new InputValue() - , - (writer, obj) => - { - if (obj is StructuredList l) - { - l.Write(writer); - } - }, - token => - { - // This is currently a proof-of-concept implementation. - // TODO: support generic structure types - try - { - return new StructuredList().Read(token); - } - catch(Exception) - { - - //Log.Warning("Failed to load structured list:" + e.Message); - return null; - } - } - ); - RegisterType(typeof(Texture3dWithViews), "Texture3dWithViews", - () => new InputValue(new Texture3dWithViews())); - RegisterType(typeof(MeshBuffers), "MeshBuffers", - () => new InputValue(null)); - - RegisterType(typeof(DataSet), "DataSet", - () => new InputValue()); - // sharpdx types - RegisterType(typeof(SharpDX.Direct3D.PrimitiveTopology), "PrimitiveTopology", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.BindFlags), "BindFlags", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.BlendOperation), "BlendOperation", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.BlendOption), "BlendOption", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.BlendState), "BlendState", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.Buffer), "Buffer", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.ColorWriteMaskFlags), "ColorWriteMaskFlags", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.Comparison), "Comparison", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.ComputeShader), "ComputeShader", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.CpuAccessFlags), "CpuAccessFlags", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.CullMode), "CullMode", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.DepthStencilState), "DepthStencilState", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.DepthStencilView), "DepthStencilView", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.FillMode), "FillMode", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.Filter), "Filter", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.GeometryShader), "GeometryShader", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.InputLayout), "InputLayout", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.PixelShader), "PixelShader", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.RenderTargetBlendDescription), "RenderTargetBlendDescription", - () => new InputValue()); - RegisterType(typeof(SharpDX.Direct3D11.RasterizerState), "RasterizerState", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.RenderTargetView), "RenderTargetView", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.ResourceOptionFlags), "ResourceOptionFlags", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.ResourceUsage), "ResourceUsage", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.SamplerState), "SamplerState", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.ShaderResourceView), "ShaderResourceView", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.Texture2D), "Texture2D", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.Texture3D), "Texture3D", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.TextureAddressMode), "TextureAddressMode", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.UnorderedAccessView), "UnorderedAccessView", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.Direct3D11.UnorderedAccessViewBufferFlags), "UnorderedAccessViewBufferFlags", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Direct3D11.VertexShader), "VertexShader", - () => new InputValue(null)); - RegisterType(typeof(SharpDX.DXGI.Format), "Format", - InputDefaultValueCreator, - (writer, obj) => writer.WriteValue(obj.ToString()), - JsonToEnumValue); - RegisterType(typeof(SharpDX.Int3), "Int3", - InputDefaultValueCreator, - (writer, obj) => - { - Int3 vec = (Int3)obj; - writer.WriteStartObject(); - writer.WriteValue("X", vec.X); - writer.WriteValue("Y", vec.Y); - writer.WriteValue("Z", vec.Z); - writer.WriteEndObject(); - }, - jsonToken => - { - int x = jsonToken["X"].Value(); - int y = jsonToken["Y"].Value(); - int z = jsonToken["Z"].Value(); - return new Int3(x, y, z); - }); - RegisterType(typeof(SharpDX.Mathematics.Interop.RawRectangle), "RawRectangle", - () => new InputValue(new RawRectangle { Left = -100, Right = 100, Bottom = -100, Top = 100 })); - RegisterType(typeof(SharpDX.Mathematics.Interop.RawViewportF), "RawViewportF", - () => new InputValue(new RawViewportF - { X = 0.0f, Y = 0.0f, Width = 100.0f, Height = 100.0f, MinDepth = 0.0f, MaxDepth = 10000.0f })); - RegisterType(typeof(SharpDX.Size2), "Size2", - InputDefaultValueCreator, - (writer, obj) => - { - Size2 vec = (Size2)obj; - writer.WriteStartObject(); - writer.WriteValue("Width", vec.Width); - writer.WriteValue("Height", vec.Height); - writer.WriteEndObject(); - }, - jsonToken => - { - int width = jsonToken["Width"].Value(); - int height = jsonToken["Height"].Value(); - return new Size2(width, height); - }); - RegisterType(typeof(SharpDX.Vector4[]), "Vector4[]", - () => new InputValue(Array.Empty())); - RegisterType(typeof(Dict), "Dict", - () => new InputValue>()); - } - - private static void RegisterType(Type type, string typeName, - Func defaultValueCreator, - Action valueToJsonConverter, - Func jsonToValueConverter) - { - RegisterType(type, typeName, defaultValueCreator); - TypeValueToJsonConverters.Entries.Add(type, valueToJsonConverter); - JsonToTypeValueConverters.Entries.Add(type, jsonToValueConverter); - } - - private static void RegisterType(Type type, string typeName, Func defaultValueCreator) - { - TypeNameRegistry.Entries.Add(type, typeName); - InputValueCreators.Entries.Add(type, defaultValueCreator); - } +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using SharpDX.Mathematics.Interop; +using T3.Core.Animation; +using T3.Core.DataTypes; +using T3.Core.DataTypes.DataSet; +using T3.Core.Operator.Slots; +using T3.Core.Resource; +using Buffer = SharpDX.Direct3D11.Buffer; +using Point = T3.Core.DataTypes.Point; +using Vector4 = System.Numerics.Vector4; + +namespace T3.Core.Model; + +public static class JsonToTypeValueConverters +{ + public static Dictionary> Entries { get; } = new(); +} + +public static class TypeValueToJsonConverters +{ + public static Dictionary> Entries { get; } = new(); +} + +public static class InputValueCreators +{ + public static Dictionary> Entries { get; } = new(); +} + +public static class TypeNameRegistry +{ + public static Dictionary Entries { get; } = new(20); +} + +public partial class SymbolData +{ + static SymbolData() + { + RegisterTypes(); + } + + private static void RegisterTypes() + { + // generic enum value from json function, must be local function + object JsonToEnumValue(JToken jsonToken) where T : struct // todo: use 7.3 and replace with enum + { + var value = jsonToken.Value(); + + if (Enum.TryParse(value, out T enumValue)) + { + return enumValue; + } + + return null; + } + + InputValue InputDefaultValueCreator() => new InputValue(); + + // build-in default types + RegisterType(typeof(float), "float", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue((float)obj), + jsonToken => jsonToken.Value()); + RegisterType(typeof(int), "int", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue((int)obj), + jsonToken => jsonToken.Value()); + RegisterType(typeof(bool), "bool", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue((bool)obj), + jsonToken => jsonToken.Value()); + RegisterType(typeof(double), "double", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue((double)obj), + jsonToken => jsonToken.Value()); + + RegisterType(typeof(string), "string", + () => new InputValue(string.Empty), + (writer, value) => writer.WriteValue((string)value), + jsonToken => jsonToken.Value()); + + // system types + RegisterType(typeof(System.Numerics.Vector2), "Vector2", + InputDefaultValueCreator, + (writer, obj) => + { + var vec = (System.Numerics.Vector2)obj; + writer.WriteStartObject(); + writer.WriteValue("X", vec.X); + writer.WriteValue("Y", vec.Y); + writer.WriteEndObject(); + }, + jsonToken => + { + float x = jsonToken["X"].Value(); + float y = jsonToken["Y"].Value(); + return new System.Numerics.Vector2(x, y); + }); + RegisterType(typeof(System.Numerics.Vector3), "Vector3", + InputDefaultValueCreator, + (writer, obj) => + { + var vec = (System.Numerics.Vector3)obj; + writer.WriteStartObject(); + writer.WriteValue("X", vec.X); + writer.WriteValue("Y", vec.Y); + writer.WriteValue("Z", vec.Z); + writer.WriteEndObject(); + }, + jsonToken => + { + float x = jsonToken["X"].Value(); + float y = jsonToken["Y"].Value(); + float z = jsonToken["Z"].Value(); + return new System.Numerics.Vector3(x, y, z); + }); + RegisterType(typeof(System.Numerics.Vector4), "Vector4", + () => new InputValue(new Vector4(1.0f, 1.0f, 1.0f, 1.0f)), + (writer, obj) => + { + var vec = (Vector4)obj; + writer.WriteStartObject(); + writer.WriteValue("X", vec.X); + writer.WriteValue("Y", vec.Y); + writer.WriteValue("Z", vec.Z); + writer.WriteValue("W", vec.W); + writer.WriteEndObject(); + }, + jsonToken => + { + float x = jsonToken["X"].Value(); + float y = jsonToken["Y"].Value(); + float z = jsonToken["Z"].Value(); + float w = jsonToken["W"].Value(); + return new Vector4(x, y, z, w); + }); + RegisterType(typeof(System.Numerics.Quaternion), "Quaternion", + () => new InputValue(System.Numerics.Quaternion.Identity), + (writer, obj) => + { + var quaternion = (System.Numerics.Quaternion)obj; + writer.WriteStartObject(); + writer.WriteValue("X", quaternion.X); + writer.WriteValue("Y", quaternion.Y); + writer.WriteValue("Z", quaternion.Z); + writer.WriteValue("W", quaternion.W); + writer.WriteEndObject(); + }, + jsonToken => + { + float x = jsonToken["X"].Value(); + float y = jsonToken["Y"].Value(); + float z = jsonToken["Z"].Value(); + float w = jsonToken["W"].Value(); + return new System.Numerics.Quaternion(x, y, z, w); + }); + + RegisterType(typeof(System.Collections.Generic.List), "List", + () => new InputValue>(new List()), + (writer, obj) => + { + var list = (List)obj; + writer.WriteStartObject(); + writer.WritePropertyName("Values"); + writer.WriteStartArray(); + list.ForEach(writer.WriteValue); + writer.WriteEndArray(); + writer.WriteEndObject(); + }, + jsonToken => + { + var entries = jsonToken["Values"]; + var list = new List(entries.Count()); + list.AddRange(entries.Select(entry => entry.Value())); + + return list; + }); + RegisterType(typeof(System.Collections.Generic.List), "List", + () => new InputValue>(new List()), + (writer, obj) => + { + var list = (List)obj; + writer.WriteStartObject(); + writer.WritePropertyName("Values"); + writer.WriteStartArray(); + list.ForEach(writer.WriteValue); + writer.WriteEndArray(); + writer.WriteEndObject(); + }, + jsonToken => + { + var entries = jsonToken["Values"]; + var list = new List(entries.Count()); + list.AddRange(entries.Select(entry => entry.Value())); + return list; + }); + + + RegisterType(typeof(System.Text.StringBuilder), "StringBuilder", + () => new InputValue(new StringBuilder())); + + RegisterType(typeof(DateTime), "DateTime", + () => new InputValue(new DateTime())); + + // t3 core types + RegisterType(typeof(BufferWithViews), "BufferWithViews", + () => new InputValue(null)); + + RegisterType(typeof(Command), "Command", + () => new InputValue(null)); + + RegisterType(typeof(Curve), "Curve", + InputDefaultValueCreator, + (writer, obj) => + { + Curve curve = (Curve)obj; + writer.WriteStartObject(); + curve?.Write(writer); + writer.WriteEndObject(); + }, + jsonToken => + { + Curve curve = new Curve(); + if (jsonToken == null || !jsonToken.HasValues) + { + curve.AddOrUpdateV(0, new VDefinition() { Value = 0 }); + curve.AddOrUpdateV(1, new VDefinition() { Value = 1 }); + } + else + { + curve.Read(jsonToken); + } + + return curve; + }); + + + RegisterType(typeof(DataTypes.Gradient), "Gradient", + InputDefaultValueCreator, + (writer, obj) => + { + Gradient gradient = (Gradient)obj; + writer.WriteStartObject(); + gradient?.Write(writer); + writer.WriteEndObject(); + }, + jsonToken => + { + Gradient gradient = new Gradient(); + if (jsonToken == null || !jsonToken.HasValues) + { + gradient = new Gradient(); + } + else + { + gradient.Read(jsonToken); + } + + return gradient; + }); + RegisterType(typeof(LegacyParticleSystem), "LegacyParticleSystem", + () => new InputValue(null)); + + RegisterType(typeof(ParticleSystem), "ParticleSystem", + () => new InputValue(null)); + + RegisterType(typeof(T3.Core.Operator.GizmoVisibility), "GizmoVisibility", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + + RegisterType(typeof(Point[]), "Point", + () => new InputValue()); + RegisterType(typeof(RenderTargetReference), "RenderTargetRef", + () => new InputValue()); + RegisterType(typeof(Object), "Object", + () => new InputValue()); + RegisterType(typeof(StructuredList), "StructuredList", + () => new InputValue() + , + (writer, obj) => + { + if (obj is StructuredList l) + { + l.Write(writer); + } + }, + token => + { + // This is currently a proof-of-concept implementation. + // TODO: support generic structure types + try + { + return new StructuredList().Read(token); + } + catch(Exception) + { + + //Log.Warning("Failed to load structured list:" + e.Message); + return null; + } + } + ); + RegisterType(typeof(Texture3dWithViews), "Texture3dWithViews", + () => new InputValue(new Texture3dWithViews())); + RegisterType(typeof(MeshBuffers), "MeshBuffers", + () => new InputValue(null)); + + RegisterType(typeof(DataSet), "DataSet", + () => new InputValue()); + // sharpdx types + RegisterType(typeof(SharpDX.Direct3D.PrimitiveTopology), "PrimitiveTopology", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.BindFlags), "BindFlags", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.BlendOperation), "BlendOperation", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.BlendOption), "BlendOption", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.BlendState), "BlendState", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.Buffer), "Buffer", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.ColorWriteMaskFlags), "ColorWriteMaskFlags", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.Comparison), "Comparison", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.ComputeShader), "ComputeShader", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.CpuAccessFlags), "CpuAccessFlags", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.CullMode), "CullMode", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.DepthStencilState), "DepthStencilState", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.DepthStencilView), "DepthStencilView", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.FillMode), "FillMode", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.Filter), "Filter", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.GeometryShader), "GeometryShader", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.InputLayout), "InputLayout", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.PixelShader), "PixelShader", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.RenderTargetBlendDescription), "RenderTargetBlendDescription", + () => new InputValue()); + RegisterType(typeof(SharpDX.Direct3D11.RasterizerState), "RasterizerState", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.RenderTargetView), "RenderTargetView", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.ResourceOptionFlags), "ResourceOptionFlags", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.ResourceUsage), "ResourceUsage", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.SamplerState), "SamplerState", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.ShaderResourceView), "ShaderResourceView", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.Texture2D), "Texture2D", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.Texture3D), "Texture3D", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.TextureAddressMode), "TextureAddressMode", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.UnorderedAccessView), "UnorderedAccessView", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.Direct3D11.UnorderedAccessViewBufferFlags), "UnorderedAccessViewBufferFlags", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Direct3D11.VertexShader), "VertexShader", + () => new InputValue(null)); + RegisterType(typeof(SharpDX.DXGI.Format), "Format", + InputDefaultValueCreator, + (writer, obj) => writer.WriteValue(obj.ToString()), + JsonToEnumValue); + RegisterType(typeof(SharpDX.Int3), "Int3", + InputDefaultValueCreator, + (writer, obj) => + { + Int3 vec = (Int3)obj; + writer.WriteStartObject(); + writer.WriteValue("X", vec.X); + writer.WriteValue("Y", vec.Y); + writer.WriteValue("Z", vec.Z); + writer.WriteEndObject(); + }, + jsonToken => + { + int x = jsonToken["X"].Value(); + int y = jsonToken["Y"].Value(); + int z = jsonToken["Z"].Value(); + return new Int3(x, y, z); + }); + RegisterType(typeof(SharpDX.Mathematics.Interop.RawRectangle), "RawRectangle", + () => new InputValue(new RawRectangle { Left = -100, Right = 100, Bottom = -100, Top = 100 })); + RegisterType(typeof(SharpDX.Mathematics.Interop.RawViewportF), "RawViewportF", + () => new InputValue(new RawViewportF + { X = 0.0f, Y = 0.0f, Width = 100.0f, Height = 100.0f, MinDepth = 0.0f, MaxDepth = 10000.0f })); + RegisterType(typeof(SharpDX.Size2), "Size2", + InputDefaultValueCreator, + (writer, obj) => + { + Size2 vec = (Size2)obj; + writer.WriteStartObject(); + writer.WriteValue("Width", vec.Width); + writer.WriteValue("Height", vec.Height); + writer.WriteEndObject(); + }, + jsonToken => + { + int width = jsonToken["Width"].Value(); + int height = jsonToken["Height"].Value(); + return new Size2(width, height); + }); + RegisterType(typeof(SharpDX.Vector4[]), "Vector4[]", + () => new InputValue(Array.Empty())); + RegisterType(typeof(Dict), "Dict", + () => new InputValue>()); + } + + private static void RegisterType(Type type, string typeName, + Func defaultValueCreator, + Action valueToJsonConverter, + Func jsonToValueConverter) + { + RegisterType(type, typeName, defaultValueCreator); + TypeValueToJsonConverters.Entries.Add(type, valueToJsonConverter); + JsonToTypeValueConverters.Entries.Add(type, jsonToValueConverter); + } + + private static void RegisterType(Type type, string typeName, Func defaultValueCreator) + { + TypeNameRegistry.Entries.Add(type, typeName); + InputValueCreators.Entries.Add(type, defaultValueCreator); + } } \ No newline at end of file diff --git a/Core/Model/SymbolData.cs b/Core/Model/SymbolData.cs index 39a1ffbe71..294a6da0ce 100644 --- a/Core/Model/SymbolData.cs +++ b/Core/Model/SymbolData.cs @@ -28,7 +28,7 @@ public SymbolData(Assembly operatorAssembly) public virtual void Load(bool enableLog) { - Console.WriteLine("Loading symbols..."); + Log.Debug("Loading symbols..."); var symbolFiles = Directory.GetFiles(OperatorTypesFolder, $"*{SymbolExtension}", SearchOption.AllDirectories); var symbolsRead = symbolFiles.AsParallel() @@ -38,7 +38,7 @@ public virtual void Load(bool enableLog) .ToList(); // Execute and bring back to main thread - Console.WriteLine("Registering loaded symbols..."); + Log.Debug("Registering loaded symbols..."); // Check if there are symbols without a file, if yes add these var instanceTypesWithoutFile = OperatorsAssembly.ExportedTypes.AsParallel() .Where(type => type.IsSubclassOf(typeof(Instance))) @@ -48,7 +48,13 @@ public virtual void Load(bool enableLog) foreach (var readSymbolResult in symbolsRead) { var symbol = readSymbolResult.Symbol; - SymbolRegistry.Entries.Add(symbol.Id, symbol); + if (!SymbolRegistry.Entries.TryAdd(symbol.Id, symbol)) + { + var existingSymbol = SymbolRegistry.Entries[symbol.Id]; + Log.Error($"Symbol {existingSymbol.Name} exists multiple times in database."); + continue; + } + instanceTypesWithoutFile.Remove(symbol.InstanceType); } @@ -57,7 +63,7 @@ public virtual void Load(bool enableLog) RegisterTypeWithoutFile(newType); } - Console.WriteLine("Applying symbol children..."); + Log.Debug("Applying symbol children..."); Parallel.ForEach(symbolsRead, ReadAndApplyChildren); void ReadAndApplyChildren(SymbolJson.SymbolReadResult readSymbolResult) diff --git a/Core/Model/SymbolJson.cs b/Core/Model/SymbolJson.cs index d885e32695..4968c9cb58 100644 --- a/Core/Model/SymbolJson.cs +++ b/Core/Model/SymbolJson.cs @@ -248,7 +248,8 @@ private static bool TryReadSymbolChild(in JsonChildResult childJsonResult, out var isDisabledJson = outputJson[JsonKeys.IsDisabled]; if (isDisabledJson != null) { - child.Outputs[outputId].IsDisabled = isDisabledJson.Value(); + if(child.Outputs.TryGetValue(outputId, out var output)) + output.IsDisabled = isDisabledJson.Value(); } } diff --git a/Core/Operator/EvaluationContext.cs b/Core/Operator/EvaluationContext.cs index 9f56b69adf..77d5e480e4 100644 --- a/Core/Operator/EvaluationContext.cs +++ b/Core/Operator/EvaluationContext.cs @@ -1,125 +1,124 @@ -using System.Collections.Generic; -using SharpDX; -using SharpDX.Direct3D11; -using T3.Core.Animation; -using T3.Core.DataTypes; -using T3.Core.Operator.Interfaces; -using T3.Core.Rendering; -using Vector3 = SharpDX.Vector3; -using Vector4 = System.Numerics.Vector4; - -namespace T3.Core.Operator -{ - public enum GizmoVisibility - { - Inherit = -1, - Off = 0, - On = 1, - } - - public class EvaluationContext - { - public EvaluationContext() - { - Reset(); - } - - public void Reset() - { - // TODO: this should be replaced with a solution that supports multiple playback sources - Playback = Playback.Current; - - LocalTime = Playback.TimeInBars; - LocalFxTime = Playback.FxTimeInBars; - PointLights.Clear(); - PbrContextSettings.SetDefaultToContext(this); - } - - public void SetViewFromCamera(ICamera camera) - { - var fov = MathUtil.DegreesToRadians(45); - var aspectRatio = (float)RequestedResolution.Width / RequestedResolution.Height; - CameraToClipSpace = Matrix.PerspectiveFovRH(fov, aspectRatio, 0.01f, 1000); - - Vector3 eye = new Vector3(camera.CameraPosition.X, camera.CameraPosition.Y, camera.CameraPosition.Z); - Vector3 target = new Vector3(camera.CameraTarget.X, camera.CameraTarget.Y, camera.CameraTarget.Z); - Vector3 up = Vector3.Up; - WorldToCamera = Matrix.LookAtRH(eye, target, up); - - ObjectToWorld = Matrix.Identity; - } - - public void SetDefaultCamera() - { - ObjectToWorld = Matrix.Identity; - WorldToCamera = Matrix.LookAtRH(new Vector3(0, 0, 2.4141f), Vector3.Zero, Vector3.Up); - var fov = MathUtil.DegreesToRadians(45); - float aspectRatio = (float)RequestedResolution.Width / RequestedResolution.Height; - CameraToClipSpace = Matrix.PerspectiveFovRH(fov, aspectRatio, 0.01f, 1000); - } - - private static ICamera _defaultCamera = new ViewCamera(); - - - #region timing - public Playback Playback { get; private set; } - - /// - /// The primary time used for user interactions and keyframe manipulation. - /// This is where there time marker in the timeline is displayed unless overridden by operators. - /// - /// While evaluating the graph it can be overridden for sub graphs by . - /// - /// Also see . and . - public double LocalTime { get; set; } - - /// - /// Although similar to KeyframeTime, this one keeps running in pause mode, if Keep Running is active. - /// While evaluating the graph it can be overridden for sub graphs by . - /// - public double LocalFxTime { get; set; } - - #endregion - - public Size2 RequestedResolution { get; set; } - - public Matrix CameraToClipSpace { get; set; } = Matrix.Identity; - public Matrix WorldToCamera { get; set; } = Matrix.Identity; - public Matrix ObjectToWorld { get; set; } = Matrix.Identity; - - // Render settings - public Buffer FogParameters { get; set; } = FogSettings.DefaultSettingsBuffer; - public Buffer PbrMaterialParams { get; set; } - public PbrMaterialTextures PbrMaterialTextures { get; set; } = new PbrMaterialTextures(); - - /// - /// A structure that is used by SetTexture - /// - public Dictionary ContextTextures { get; set; } = new(10); - public Texture2D PrbPrefilteredSpecular { get; set; } - public PointLightStack PointLights { get; } = new(); - - /// - /// This should be set by RenderTargets and other ops can could be directly used by SetFog. - /// - public System.Numerics.Vector4 BackgroundColor { get; set; } = new(0.1f, 0.1f, 0.1f, 1.0f); - - /// - /// Can be set by [SetMaterial] [Group] and other ops to fade out groups - /// - public System.Numerics.Vector4 ForegroundColor { get; set; } = Vector4.One; - - public GizmoVisibility ShowGizmos { get; set; } - - public Dictionary FloatVariables { get; } = new(); - public Dictionary IntVariables { get; } = new(); - public StructuredList IteratedList { get; set; } - public int IteratedListIndex { get; set; } - public bool BypassCameras { get; set; } - - public ParticleSystem ParticleSystem; - - - } - +using System.Collections.Generic; +using SharpDX; +using SharpDX.Direct3D11; +using T3.Core.Animation; +using T3.Core.DataTypes; +using T3.Core.Operator.Interfaces; +using T3.Core.Rendering; +using Vector3 = SharpDX.Vector3; +using Vector4 = System.Numerics.Vector4; + +namespace T3.Core.Operator +{ + public enum GizmoVisibility + { + Inherit = -1, + Off = 0, + On = 1, + IfSelected = 2, + } + + public class EvaluationContext + { + public EvaluationContext() + { + Reset(); + } + + public void Reset() + { + // TODO: this should be replaced with a solution that supports multiple playback sources + Playback = Playback.Current; + + LocalTime = Playback.TimeInBars; + LocalFxTime = Playback.FxTimeInBars; + PointLights.Clear(); + PbrContextSettings.SetDefaultToContext(this); + } + + public void SetViewFromCamera(ICamera camera) + { + var fov = MathUtil.DegreesToRadians(45); + var aspectRatio = (float)RequestedResolution.Width / RequestedResolution.Height; + CameraToClipSpace = Matrix.PerspectiveFovRH(fov, aspectRatio, 0.01f, 1000); + + Vector3 eye = new Vector3(camera.CameraPosition.X, camera.CameraPosition.Y, camera.CameraPosition.Z); + Vector3 target = new Vector3(camera.CameraTarget.X, camera.CameraTarget.Y, camera.CameraTarget.Z); + Vector3 up = Vector3.Up; + WorldToCamera = Matrix.LookAtRH(eye, target, up); + + ObjectToWorld = Matrix.Identity; + } + + public void SetDefaultCamera() + { + ObjectToWorld = Matrix.Identity; + WorldToCamera = Matrix.LookAtRH(new Vector3(0, 0, 2.4141f), Vector3.Zero, Vector3.Up); + var fov = MathUtil.DegreesToRadians(45); + float aspectRatio = (float)RequestedResolution.Width / RequestedResolution.Height; + CameraToClipSpace = Matrix.PerspectiveFovRH(fov, aspectRatio, 0.01f, 1000); + } + + private static ICamera _defaultCamera = new ViewCamera(); + + + #region timing + public Playback Playback { get; private set; } + + /// + /// The primary time used for user interactions and keyframe manipulation. + /// This is where there time marker in the timeline is displayed unless overridden by operators. + /// + /// While evaluating the graph it can be overridden for sub graphs by . + /// + /// Also see . and . + public double LocalTime { get; set; } + + /// + /// Although similar to KeyframeTime, this one keeps running in pause mode, if Keep Running is active. + /// While evaluating the graph it can be overridden for sub graphs by . + /// + public double LocalFxTime { get; set; } + + #endregion + + public Size2 RequestedResolution { get; set; } + + public Matrix CameraToClipSpace { get; set; } = Matrix.Identity; + public Matrix WorldToCamera { get; set; } = Matrix.Identity; + public Matrix ObjectToWorld { get; set; } = Matrix.Identity; + + // Render settings + public Buffer FogParameters { get; set; } = FogSettings.DefaultSettingsBuffer; + public Buffer PbrMaterialParams { get; set; } + public PbrMaterialTextures PbrMaterialTextures { get; set; } = new PbrMaterialTextures(); + + /// + /// A structure that is used by SetTexture + /// + public Dictionary ContextTextures { get; set; } = new(10); + public Texture2D PrbPrefilteredSpecular { get; set; } + public PointLightStack PointLights { get; } = new(); + + /// + /// This should be set by RenderTargets and other ops can could be directly used by SetFog. + /// + public System.Numerics.Vector4 BackgroundColor { get; set; } = new(0.1f, 0.1f, 0.1f, 1.0f); + + /// + /// Can be set by [SetMaterial] [Group] and other ops to fade out groups + /// + public System.Numerics.Vector4 ForegroundColor { get; set; } = Vector4.One; + + public GizmoVisibility ShowGizmos { get; set; } + + public Dictionary FloatVariables { get; } = new(); + public Dictionary IntVariables { get; } = new(); + public StructuredList IteratedList { get; set; } + public int IteratedListIndex { get; set; } + public bool BypassCameras { get; set; } + + public LegacyParticleSystem LegacyParticleSystem; + public ParticleSystem ParticleSystem; + } } \ No newline at end of file diff --git a/Core/Operator/Interfaces/ICamera.cs b/Core/Operator/Interfaces/ICamera.cs index ac2ecc3fd3..3257cec38c 100644 --- a/Core/Operator/Interfaces/ICamera.cs +++ b/Core/Operator/Interfaces/ICamera.cs @@ -1,26 +1,83 @@ -using SharpDX; -using Vector3 = System.Numerics.Vector3; - -namespace T3.Core.Operator.Interfaces -{ - public interface ICamera - { - Vector3 CameraPosition { get; set; } - Vector3 CameraTarget { get; set; } - float CameraRoll { get; set; } - - SharpDX.Matrix WorldToCamera { get; } - SharpDX.Matrix CameraToClipSpace { get; } - } - - // Mock view internal fallback camera (if no operator selected) - // Todo: Find a better location of this class - public class ViewCamera : ICamera - { - public Vector3 CameraPosition { get; set; } = new Vector3(0, 0, 2.416f); - public Vector3 CameraTarget { get; set; } - public float CameraRoll { get; set; } - public Matrix WorldToCamera { get; } - public Matrix CameraToClipSpace { get; } - } +using SharpDX; +using T3.Core.Utils; +using Vector3 = System.Numerics.Vector3; + +namespace T3.Core.Operator.Interfaces +{ + public interface ICamera + { + Vector3 CameraPosition { get; set; } + Vector3 CameraTarget { get; set; } + float CameraRoll { get; set; } + + CameraDefinition CameraDefinition { get; } + SharpDX.Matrix WorldToCamera { get; } + SharpDX.Matrix CameraToClipSpace { get; } + } + + public struct CameraDefinition + { + public System.Numerics.Vector2 NearFarClip; + public System.Numerics.Vector2 ViewPortShift; + public System.Numerics.Vector3 PositionOffset; + public System.Numerics.Vector3 Position; + public System.Numerics.Vector3 Target; + public System.Numerics.Vector3 Up; + public float AspectRatio; + public float Fov; + public float Roll; + public System.Numerics.Vector3 RotationOffset; + public bool OffsetAffectsTarget; + + public static CameraDefinition Blend(CameraDefinition a, CameraDefinition b, float f) + { + return new CameraDefinition + { + NearFarClip = MathUtils.Lerp(a.NearFarClip, b.NearFarClip, f), + ViewPortShift = MathUtils.Lerp(a.ViewPortShift, b.ViewPortShift, f), + PositionOffset = MathUtils.Lerp(a.PositionOffset, b.PositionOffset, f), + Position = MathUtils.Lerp(a.Position, b.Position, f), + Target = MathUtils.Lerp(a.Target, b.Target, f), + Up = MathUtils.Lerp(a.Up, b.Up, f), + AspectRatio = MathUtils.Lerp(a.AspectRatio, b.AspectRatio, f), + Fov = MathUtils.Lerp(a.Fov, b.Fov, f), + Roll = MathUtils.Lerp(a.Roll, b.Roll, f), + RotationOffset = MathUtils.Lerp(a.RotationOffset, b.RotationOffset, f), + OffsetAffectsTarget = f < 0.5 ? a.OffsetAffectsTarget : b.OffsetAffectsTarget, + }; + } + + public void BuildProjectionMatrices(out Matrix camToClipSpace, out Matrix worldToCamera) + { + camToClipSpace = Matrix.PerspectiveFovRH(Fov, AspectRatio, NearFarClip.X, NearFarClip.Y); + camToClipSpace.M31 = ViewPortShift.X; + camToClipSpace.M32 = ViewPortShift.Y; + + var eye = Position; + if (!OffsetAffectsTarget) + eye += PositionOffset; + + var worldToCameraRoot = Matrix.LookAtRH(eye.ToSharpDx(), Target.ToSharpDx(), Up.ToSharpDx()); + var rollRotation = Matrix.RotationAxis(new SharpDX.Vector3(0, 0, 1), -Roll * MathUtils.ToRad); + var additionalTranslation = OffsetAffectsTarget ? Matrix.Translation(PositionOffset.X, PositionOffset.Y, PositionOffset.Z) : Matrix.Identity; + + var additionalRotation = Matrix.RotationYawPitchRoll(MathUtil.DegreesToRadians(RotationOffset.Y), + MathUtil.DegreesToRadians(RotationOffset.X), + MathUtil.DegreesToRadians(RotationOffset.Z)); + + worldToCamera = worldToCameraRoot * rollRotation * additionalRotation * additionalTranslation; + } + } + + // Mock view internal fallback camera (if no operator selected) + // Todo: Find a better location of this class + public class ViewCamera : ICamera + { + public Vector3 CameraPosition { get; set; } = new Vector3(0, 0, 2.416f); + public Vector3 CameraTarget { get; set; } + public float CameraRoll { get; set; } + public Matrix WorldToCamera { get; } + public Matrix CameraToClipSpace { get; } + public CameraDefinition CameraDefinition => new(); // Not implemetned + } } \ No newline at end of file diff --git a/Core/Operator/Interfaces/ICustomDropdownHolder.cs b/Core/Operator/Interfaces/ICustomDropdownHolder.cs new file mode 100644 index 0000000000..9267d4d0af --- /dev/null +++ b/Core/Operator/Interfaces/ICustomDropdownHolder.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace T3.Core.Operator.Interfaces; + +/// +/// An interface that can be used by operators that need to generate selection lists +/// on runtime (e.g. input sources that are only available after startup) +/// +/// This interface can then be activated by adding a string input with usage "custom input" +/// in the parameter settings. +/// +public interface ICustomDropdownHolder +{ + string GetValueForInput(Guid inputId); + IEnumerable GetOptionsForInput(Guid inputId); + void HandleResultForInput(Guid inputId, string result); +} \ No newline at end of file diff --git a/Core/Operator/Slots/InputSlot.cs b/Core/Operator/Slots/InputSlot.cs index 10d84be0f0..7280561217 100644 --- a/Core/Operator/Slots/InputSlot.cs +++ b/Core/Operator/Slots/InputSlot.cs @@ -53,6 +53,7 @@ public void SetTypedInputValue(T newValue) { Input.IsDefault = false; TypedInputValue.Value = newValue; + Value = newValue; DirtyFlag.Invalidate(); } diff --git a/Core/Operator/Slots/TimeClipSlot.cs b/Core/Operator/Slots/TimeClipSlot.cs index 375d1256c5..8e3d4146be 100644 --- a/Core/Operator/Slots/TimeClipSlot.cs +++ b/Core/Operator/Slots/TimeClipSlot.cs @@ -1,6 +1,7 @@ using System; using T3.Core.Animation; using T3.Core.IO; +using T3.Core.Logging; namespace T3.Core.Operator.Slots { @@ -44,7 +45,14 @@ private void UpdateWithTimeRangeCheck(EvaluationContext context) double factor = (context.LocalTime - TimeClip.TimeRange.Start) / (TimeClip.TimeRange.End - TimeClip.TimeRange.Start); context.LocalTime = factor * (TimeClip.SourceRange.End - TimeClip.SourceRange.Start) + TimeClip.SourceRange.Start; - _baseUpdateAction(context); + if (_baseUpdateAction == null) + { + Log.Warning("Ignoring invalid time clip update action", Parent); + } + else + { + _baseUpdateAction(context); + } context.LocalTime = prevTime; LastUpdateStatus = UpdateStates.Active; diff --git a/Core/Operator/Symbol.cs b/Core/Operator/Symbol.cs index 6ad4ee387d..0e3f1a71a0 100644 --- a/Core/Operator/Symbol.cs +++ b/Core/Operator/Symbol.cs @@ -823,6 +823,11 @@ public void InvalidateInputInAllChildInstances(IInputSlot inputSlot) { var childId = inputSlot.Parent.SymbolChildId; var inputId = inputSlot.Id; + InvalidateInputInAllChildInstances(inputId, childId); + } + + public void InvalidateInputInAllChildInstances(Guid inputId, Guid childId) + { foreach (var symbolInstance in InstancesOfSymbol) { var childInstance = symbolInstance.Children.Single(c => c.SymbolChildId == childId); @@ -830,6 +835,7 @@ public void InvalidateInputInAllChildInstances(IInputSlot inputSlot) slot.DirtyFlag.Invalidate(); } } + /// /// Invalidates all instances of a symbol input (e.g. if that input's default was modified) diff --git a/Core/Operator/SymbolChild.cs b/Core/Operator/SymbolChild.cs index 54cb84edeb..a3dcb072a9 100644 --- a/Core/Operator/SymbolChild.cs +++ b/Core/Operator/SymbolChild.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using SharpDX.Direct3D11; using T3.Core.DataTypes; using T3.Core.Operator.Slots; @@ -163,6 +164,15 @@ private bool IsBypassable() if(mainInput.DefaultValue.ValueType == typeof(float)) return true; + if(mainInput.DefaultValue.ValueType == typeof(Vector2)) + return true; + + if(mainInput.DefaultValue.ValueType == typeof(Vector3)) + return true; + + if(mainInput.DefaultValue.ValueType == typeof(string)) + return true; + return false; } @@ -241,6 +251,38 @@ private void SetBypassed(bool shouldBypass) floatOutput.RestoreUpdateAction(); } break; + + case Slot vec2Output when mainInputSlot is Slot vec2Input: + if (shouldBypass) + { + wasByPassed= vec2Output.TrySetBypassToInput(vec2Input); + } + else + { + vec2Output.RestoreUpdateAction(); + } + break; + case Slot vec3Output when mainInputSlot is Slot vec3Input: + if (shouldBypass) + { + wasByPassed= vec3Output.TrySetBypassToInput(vec3Input); + } + else + { + vec3Output.RestoreUpdateAction(); + } + break; + case Slot stringOutput when mainInputSlot is Slot stringInput: + if (shouldBypass) + { + wasByPassed= stringOutput.TrySetBypassToInput(stringInput); + } + else + { + stringOutput.RestoreUpdateAction(); + } + break; + } _isBypassed = wasByPassed; diff --git a/Operators/Utils/ICameraPropertiesProvider.cs b/Core/Rendering/ICameraPropertiesProvider.cs similarity index 89% rename from Operators/Utils/ICameraPropertiesProvider.cs rename to Core/Rendering/ICameraPropertiesProvider.cs index c3d140de86..5eb3d53e94 100644 --- a/Operators/Utils/ICameraPropertiesProvider.cs +++ b/Core/Rendering/ICameraPropertiesProvider.cs @@ -1,6 +1,6 @@ using SharpDX; -namespace T3.Operators.Utils +namespace T3.Core.Rendering { public interface ICameraPropertiesProvider { diff --git a/Core/Rendering/ObjMesh.cs b/Core/Rendering/ObjMesh.cs index 700aca2f91..6352aea92b 100644 --- a/Core/Rendering/ObjMesh.cs +++ b/Core/Rendering/ObjMesh.cs @@ -277,6 +277,12 @@ private void InitializeVertices() _distinctVertices = new List(); for (var faceIndex = 0; faceIndex < Faces.Count; faceIndex++) { + if (faceIndex >= Faces.Count) + { + Log.Warning($"Skipping out of range {faceIndex} >= {Faces.Count} face index"); + faceIndex = 0; + } + var face = Faces[faceIndex]; SortInMergedVertex(0, face.V0, face.V0n, face.V0t, faceIndex); diff --git a/Core/Rendering/PrbDataTypes.cs b/Core/Rendering/PrbDataTypes.cs index e52591fa7f..7085ea4723 100644 --- a/Core/Rendering/PrbDataTypes.cs +++ b/Core/Rendering/PrbDataTypes.cs @@ -1,207 +1,207 @@ -using System; -using System.Runtime.InteropServices; -using SharpDX; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using T3.Core.Logging; -using T3.Core.Operator; -using T3.Core.Resource; -using Buffer = SharpDX.Direct3D11.Buffer; -using Vector4 = System.Numerics.Vector4; - -namespace T3.Core.Rendering -{ - [StructLayout(LayoutKind.Explicit, Size = Stride)] - public struct PbrVertex - { - [FieldOffset(0)] - public SharpDX.Vector3 Position; - - [FieldOffset(3 * 4)] - public SharpDX.Vector3 Normal; - - [FieldOffset(6 * 4)] - public SharpDX.Vector3 Tangent; - - [FieldOffset(9 * 4)] - public SharpDX.Vector3 Bitangent; - - [FieldOffset(12 * 4)] - public SharpDX.Vector2 Texcoord; - - [FieldOffset(14 * 4)] - public float Selection; - - [FieldOffset(15 * 4)] - private float __padding; - - public const int Stride = 16 * 4; - } - - [StructLayout(LayoutKind.Explicit, Size = 4 * 4)] - public struct PbrFace - { - [FieldOffset(0)] - public SharpDX.Int3 VertexIndices; - - [FieldOffset(3 * 4)] - private readonly float __padding; - } - - public static class PbrContextSettings - { - public static void SetDefaultToContext(EvaluationContext context) - { - if (!_wasInitialized) - Init(); - - context.PbrMaterialParams = _defaultParameterBuffer; - context.PbrMaterialTextures.AlbedoColorMap = _baseColorMapSrv; - context.PbrMaterialTextures.NormalMap = _normalMapSrv; - context.PbrMaterialTextures.RoughnessSpecularMetallicOcclusionMap = _rsmoMapSrv; - context.PbrMaterialTextures.EmissiveColorMap = _emissiveColorMapSrv; - context.PbrMaterialTextures.BrdfLookUpMap = _pbrLookUpTexture; - context.ContextTextures["PrefilteredSpecular"] = _prefilteredBrdfTexture; - } - - private static void Init() - { - var content = new PbrMaterialParams - { - BaseColor = Vector4.One, - EmissiveColor = new Vector4(0, 0, 0, 1), - Roughness = 0.5f, - Specular = 10, - Metal = 0 - }; - ResourceManager.SetupConstBuffer(content, ref _defaultParameterBuffer); - - var resourceManager = ResourceManager.Instance(); - var device = ResourceManager.Device; - - WhitePixelTexture = CreateFallBackTexture(new Vector4(1, 1, 1, 1)); - _baseColorMapSrv = new ShaderResourceView(device, WhitePixelTexture); - _emissiveColorMapSrv = new ShaderResourceView(device, WhitePixelTexture); - - RsmoFallbackTexture = CreateFallBackTexture(new Vector4(0, 1, 0, 0)); - _rsmoMapSrv = new ShaderResourceView(device, RsmoFallbackTexture); - - NormalFallbackTexture = CreateFallBackTexture(new Vector4(0.5f, 0.5f, 1, 0)); - _normalMapSrv = new ShaderResourceView(device, NormalFallbackTexture); - - _pbrLookUpTexture = LoadTextureAsSRV(@"Resources\common\images\BRDF-LookUp.png"); - _prefilteredBrdfTexture = LoadTexture(@"Resources\common\HDRI\studio_small_08-prefiltered.dds"); - - _wasInitialized = true; - } - - private static Texture2D CreateFallBackTexture(Vector4 c) - { - var resourceManager = ResourceManager.Instance(); - var device = ResourceManager.Device; - - var colorDesc = new Texture2DDescription() - { - ArraySize = 1, - BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource | BindFlags.UnorderedAccess, - CpuAccessFlags = CpuAccessFlags.None, - Format = Format.R16G16B16A16_Float, - Width = 1, - Height = 1, - MipLevels = 0, - OptionFlags = ResourceOptionFlags.None, - SampleDescription = new SampleDescription(1, 0), - Usage = ResourceUsage.Default - }; - - var colorBuffer = new Texture2D(device, colorDesc); - var colorBufferRtv = new RenderTargetView(device, colorBuffer); - device.ImmediateContext.ClearRenderTargetView(colorBufferRtv, new Color(c.X, c.Y, c.Z, c.W)); - return colorBuffer; - } - - private static ShaderResourceView LoadTextureAsSRV(string imagePath) - { - var resourceManager = ResourceManager.Instance(); - try - { - var (textureResId, srvResId) = resourceManager.CreateTextureFromFile(imagePath, () => { }); - - if (ResourceManager.ResourcesById.TryGetValue(srvResId, out var resource2) && resource2 is ShaderResourceViewResource srvResource) - return srvResource.ShaderResourceView; - - Log.Warning($"Failed loading texture {imagePath}"); - } - catch(Exception e) - { - Log.Warning($"Failed loading texture {imagePath} " + e ); - } - return null; - } - - private static Texture2D LoadTexture(string imagePath) - { - var resourceManager = ResourceManager.Instance(); - try - { - var (textureResId, srvResId) = resourceManager.CreateTextureFromFile(imagePath, () => { }); - if (ResourceManager.ResourcesById.TryGetValue(textureResId, out var resource1) && resource1 is Texture2dResource textureResource) - return textureResource.Texture; - - Log.Warning($"Failed loading texture {imagePath}"); - } - catch(Exception e) - { - Log.Warning($"Failed loading texture {imagePath} " + e ); - } - return null; - } - - - private static ShaderResourceView _baseColorMapSrv; - private static ShaderResourceView _rsmoMapSrv; - private static ShaderResourceView _normalMapSrv; - private static ShaderResourceView _emissiveColorMapSrv; - private static ShaderResourceView _pbrLookUpTexture; - private static Texture2D _prefilteredBrdfTexture; - private static Buffer _defaultParameterBuffer = null; - - public static Texture2D WhitePixelTexture; - public static Texture2D RsmoFallbackTexture; - public static Texture2D NormalFallbackTexture; - private static bool _wasInitialized; - } - - public class PbrMaterialTextures - { - public ShaderResourceView AlbedoColorMap; - public ShaderResourceView EmissiveColorMap; - public ShaderResourceView RoughnessSpecularMetallicOcclusionMap; - public ShaderResourceView NormalMap; - public ShaderResourceView BrdfLookUpMap; - } - - [StructLayout(LayoutKind.Explicit, Size = PbrMaterialParams.Stride)] - public struct PbrMaterialParams - { - [FieldOffset(0)] - public Vector4 BaseColor; - - [FieldOffset(4 * 4)] - public Vector4 EmissiveColor; - - [FieldOffset(8 * 4)] - public float Roughness; - - [FieldOffset(9 * 4)] - public float Specular; - - [FieldOffset(10 * 4)] - public float Metal; - - [FieldOffset(11 * 4)] - private float __padding; - - public const int Stride = 12 * 4; - } +using System; +using System.Runtime.InteropServices; +using SharpDX; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using T3.Core.Logging; +using T3.Core.Operator; +using T3.Core.Resource; +using Buffer = SharpDX.Direct3D11.Buffer; +using Vector4 = System.Numerics.Vector4; + +namespace T3.Core.Rendering +{ + [StructLayout(LayoutKind.Explicit, Size = Stride)] + public struct PbrVertex + { + [FieldOffset(0)] + public SharpDX.Vector3 Position; + + [FieldOffset(3 * 4)] + public SharpDX.Vector3 Normal; + + [FieldOffset(6 * 4)] + public SharpDX.Vector3 Tangent; + + [FieldOffset(9 * 4)] + public SharpDX.Vector3 Bitangent; + + [FieldOffset(12 * 4)] + public SharpDX.Vector2 Texcoord; + + [FieldOffset(14 * 4)] + public float Selection; + + [FieldOffset(15 * 4)] + private float __padding; + + public const int Stride = 16 * 4; + } + + [StructLayout(LayoutKind.Explicit, Size = 4 * 4)] + public struct PbrFace + { + [FieldOffset(0)] + public SharpDX.Int3 VertexIndices; + + [FieldOffset(3 * 4)] + private readonly float __padding; + } + + public static class PbrContextSettings + { + public static void SetDefaultToContext(EvaluationContext context) + { + if (!_wasInitialized) + Init(); + + context.PbrMaterialParams = _defaultParameterBuffer; + context.PbrMaterialTextures.AlbedoColorMap = _baseColorMapSrv; + context.PbrMaterialTextures.NormalMap = _normalMapSrv; + context.PbrMaterialTextures.RoughnessMetallicOcclusionMap = _rsmoMapSrv; + context.PbrMaterialTextures.EmissiveColorMap = _emissiveColorMapSrv; + context.PbrMaterialTextures.BrdfLookUpMap = _pbrLookUpTexture; + context.ContextTextures["PrefilteredSpecular"] = _prefilteredBrdfTexture; + } + + private static void Init() + { + var content = new PbrMaterialParams + { + BaseColor = Vector4.One, + EmissiveColor = new Vector4(0, 0, 0, 1), + Roughness = 0.5f, + Specular = 10, + Metal = 0 + }; + ResourceManager.SetupConstBuffer(content, ref _defaultParameterBuffer); + + var resourceManager = ResourceManager.Instance(); + var device = ResourceManager.Device; + + WhitePixelTexture = CreateFallBackTexture(new Vector4(1, 1, 1, 1)); + _baseColorMapSrv = new ShaderResourceView(device, WhitePixelTexture); + _emissiveColorMapSrv = new ShaderResourceView(device, WhitePixelTexture); + + RsmoFallbackTexture = CreateFallBackTexture(new Vector4(1, 0, 1, 0)); + _rsmoMapSrv = new ShaderResourceView(device, RsmoFallbackTexture); + + NormalFallbackTexture = CreateFallBackTexture(new Vector4(0.5f, 0.5f, 1, 0)); + _normalMapSrv = new ShaderResourceView(device, NormalFallbackTexture); + + _pbrLookUpTexture = LoadTextureAsSRV(@"Resources\common\images\BRDF-LookUp.dds"); + _prefilteredBrdfTexture = LoadTexture(@"Resources\common\HDRI\studio_small_08-prefiltered.dds"); + + _wasInitialized = true; + } + + private static Texture2D CreateFallBackTexture(Vector4 c) + { + var resourceManager = ResourceManager.Instance(); + var device = ResourceManager.Device; + + var colorDesc = new Texture2DDescription() + { + ArraySize = 1, + BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource | BindFlags.UnorderedAccess, + CpuAccessFlags = CpuAccessFlags.None, + Format = Format.R16G16B16A16_Float, + Width = 1, + Height = 1, + MipLevels = 0, + OptionFlags = ResourceOptionFlags.None, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default + }; + + var colorBuffer = new Texture2D(device, colorDesc); + var colorBufferRtv = new RenderTargetView(device, colorBuffer); + device.ImmediateContext.ClearRenderTargetView(colorBufferRtv, new Color(c.X, c.Y, c.Z, c.W)); + return colorBuffer; + } + + private static ShaderResourceView LoadTextureAsSRV(string imagePath) + { + var resourceManager = ResourceManager.Instance(); + try + { + var (textureResId, srvResId) = resourceManager.CreateTextureFromFile(imagePath, () => { }); + + if (ResourceManager.ResourcesById.TryGetValue(srvResId, out var resource2) && resource2 is ShaderResourceViewResource srvResource) + return srvResource.ShaderResourceView; + + Log.Warning($"Failed loading texture {imagePath}"); + } + catch(Exception e) + { + Log.Warning($"Failed loading texture {imagePath} " + e ); + } + return null; + } + + private static Texture2D LoadTexture(string imagePath) + { + var resourceManager = ResourceManager.Instance(); + try + { + var (textureResId, srvResId) = resourceManager.CreateTextureFromFile(imagePath, () => { }); + if (ResourceManager.ResourcesById.TryGetValue(textureResId, out var resource1) && resource1 is Texture2dResource textureResource) + return textureResource.Texture; + + Log.Warning($"Failed loading texture {imagePath}"); + } + catch(Exception e) + { + Log.Warning($"Failed loading texture {imagePath} " + e ); + } + return null; + } + + + private static ShaderResourceView _baseColorMapSrv; + private static ShaderResourceView _rsmoMapSrv; + private static ShaderResourceView _normalMapSrv; + private static ShaderResourceView _emissiveColorMapSrv; + private static ShaderResourceView _pbrLookUpTexture; + private static Texture2D _prefilteredBrdfTexture; + private static Buffer _defaultParameterBuffer = null; + + public static Texture2D WhitePixelTexture; + public static Texture2D RsmoFallbackTexture; + public static Texture2D NormalFallbackTexture; + private static bool _wasInitialized; + } + + public class PbrMaterialTextures + { + public ShaderResourceView AlbedoColorMap; + public ShaderResourceView EmissiveColorMap; + public ShaderResourceView RoughnessMetallicOcclusionMap; + public ShaderResourceView NormalMap; + public ShaderResourceView BrdfLookUpMap; + } + + [StructLayout(LayoutKind.Explicit, Size = PbrMaterialParams.Stride)] + public struct PbrMaterialParams + { + [FieldOffset(0)] + public Vector4 BaseColor; + + [FieldOffset(4 * 4)] + public Vector4 EmissiveColor; + + [FieldOffset(8 * 4)] + public float Roughness; + + [FieldOffset(9 * 4)] + public float Specular; + + [FieldOffset(10 * 4)] + public float Metal; + + [FieldOffset(11 * 4)] + private float __padding; + + public const int Stride = 12 * 4; + } } \ No newline at end of file diff --git a/Core/Rendering/TransformBufferLayout.cs b/Core/Rendering/TransformBufferLayout.cs new file mode 100644 index 0000000000..1b406d6998 --- /dev/null +++ b/Core/Rendering/TransformBufferLayout.cs @@ -0,0 +1,69 @@ +using System.Runtime.InteropServices; +using SharpDX; + +[StructLayout(LayoutKind.Explicit, Size = 4 * 4 * 4 * 10)] +public struct TransformBufferLayout +{ + public TransformBufferLayout(Matrix cameraToClipSpace, Matrix worldToCamera, Matrix objectToWorld) + { + Matrix clipSpaceToCamera = cameraToClipSpace; + clipSpaceToCamera.Invert(); + Matrix cameraToWorld = worldToCamera; + cameraToWorld.Invert(); + Matrix worldToObject = objectToWorld; + worldToObject.Invert(); + + CameraToClipSpace = cameraToClipSpace; + ClipSpaceToCamera = clipSpaceToCamera; + WorldToCamera = worldToCamera; + CameraToWorld = cameraToWorld; + WorldToClipSpace = Matrix.Multiply(worldToCamera, cameraToClipSpace); + ClipSpaceToWorld = Matrix.Multiply(clipSpaceToCamera, cameraToWorld); + ObjectToWorld = objectToWorld; + WorldToObject = worldToObject; + ObjectToCamera = Matrix.Multiply(objectToWorld, worldToCamera); + ObjectToClipSpace = Matrix.Multiply(ObjectToCamera, cameraToClipSpace); + + // transpose all as mem layout in hlsl constant buffer is row based + CameraToClipSpace.Transpose(); + ClipSpaceToCamera.Transpose(); + WorldToCamera.Transpose(); + CameraToWorld.Transpose(); + WorldToClipSpace.Transpose(); + ClipSpaceToWorld.Transpose(); + ObjectToWorld.Transpose(); + WorldToObject.Transpose(); + ObjectToCamera.Transpose(); + ObjectToClipSpace.Transpose(); + } + + [FieldOffset(0)] + public Matrix CameraToClipSpace; + + [FieldOffset(64)] + public Matrix ClipSpaceToCamera; + + [FieldOffset(128)] + public Matrix WorldToCamera; + + [FieldOffset(192)] + public Matrix CameraToWorld; + + [FieldOffset(256)] + public Matrix WorldToClipSpace; + + [FieldOffset(320)] + public Matrix ClipSpaceToWorld; + + [FieldOffset(384)] + public Matrix ObjectToWorld; + + [FieldOffset(448)] + public Matrix WorldToObject; + + [FieldOffset(512)] + public Matrix ObjectToCamera; + + [FieldOffset(576)] + public Matrix ObjectToClipSpace; +} \ No newline at end of file diff --git a/Core/Resource/ResourceManager.cs b/Core/Resource/ResourceManager.cs index cc54e335cc..c62579f338 100644 --- a/Core/Resource/ResourceManager.cs +++ b/Core/Resource/ResourceManager.cs @@ -369,10 +369,21 @@ public Stream Open(IncludeType type, string fileName, Stream parentStream) { _streamReader = new StreamReader(Path.Combine(ResourcesFolder, fileName)); } - catch(DirectoryNotFoundException e ) + catch (DirectoryNotFoundException rs_e) { - Log.Error($"Can't open file {ResourcesFolder}/{fileName} {e.Message}"); - return null; + try + { + _streamReader = new StreamReader(Path.Combine( + new FileInfo(((System.IO.FileStream)parentStream).Name).DirectoryName.ToString(), + fileName + )); + } + catch (DirectoryNotFoundException in_e) + { + Log.Error($"Included file {fileName} wasn't found in {ResourcesFolder} or its parent folder " + + $"({rs_e.Message}, {in_e.Message})"); + return null; + } } return _streamReader.BaseStream; } @@ -405,18 +416,26 @@ internal static bool CompileShaderFromFile(string srcFile, string entry return false; } - blob?.Dispose(); - blob = compilationResult.Bytecode; + try + { + blob?.Dispose(); + blob = compilationResult.Bytecode; - shader?.Dispose(); + shader?.Dispose(); - // As shader type is generic we've to use Activator and PropertyInfo to create/set the shader object - Type shaderType = typeof(TShader); - shader = (TShader)Activator.CreateInstance(shaderType, Device, blob.Data, null); - PropertyInfo debugNameInfo = shaderType.GetProperty("DebugName"); - debugNameInfo?.SetValue(shader, name); - LastShaderError = null; - return true; + // As shader type is generic we've to use Activator and PropertyInfo to create/set the shader object + Type shaderType = typeof(TShader); + shader = (TShader)Activator.CreateInstance(shaderType, Device, blob.Data, null); + PropertyInfo debugNameInfo = shaderType.GetProperty("DebugName"); + debugNameInfo?.SetValue(shader, name); + LastShaderError = null; + return true; + } + catch (Exception e) + { + Log.Error($"Shader error: Failed to apply shader byte code after compilation: " + e.Message); + return false; + } } private static void CompileShaderFromSource(string shaderSource, string entryPoint, string name, string profile, ref TShader shader, ref ShaderBytecode blob) diff --git a/Core/Utils/MathUtils.cs b/Core/Utils/MathUtils.cs index 15abe245c8..87d71b6488 100644 --- a/Core/Utils/MathUtils.cs +++ b/Core/Utils/MathUtils.cs @@ -138,8 +138,19 @@ public static float[] ToArray(this Vector4 vec4) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Lerp(float a, float b, float t) { - return (float)(a + (b - a) * t); + return a + (b - a) * t; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float LerpAngle(float from, float to, float t) + { + var delta = Fmod((from - to), 2* MathF.PI); + if (delta > MathF.PI) + delta -= 2* MathF.PI; + + return from - delta * t; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Fmod(float v, float mod) diff --git a/Editor/App/ImGuiDx11RenderForm.cs b/Editor/App/ImGuiDx11RenderForm.cs index 9109a71b8e..bacf19e9dc 100644 --- a/Editor/App/ImGuiDx11RenderForm.cs +++ b/Editor/App/ImGuiDx11RenderForm.cs @@ -3,6 +3,7 @@ using ImGuiNET; using SharpDX.Windows; using T3.Core.IO; +using T3.Core.Logging; // ReSharper disable InconsistentNaming // ReSharper disable IdentifierTypo @@ -53,137 +54,149 @@ public ImGuiDx11RenderForm(string title) protected override void WndProc(ref System.Windows.Forms.Message m) { - var filterAltKeyToPreventFocusLoss = (m.Msg == WM_SYSKEYDOWN || m.Msg == WM_SYSKEYUP) && (int)m.WParam == VK_ALT; - if (!filterAltKeyToPreventFocusLoss) - base.WndProc(ref m); + try + { - foreach(var inputMethod in InputMethods) - inputMethod.ProcessMessage(m); - var isViewer = this == ProgramWindows.Viewer?.Form; + var filterAltKeyToPreventFocusLoss = (m.Msg == WM_SYSKEYDOWN || m.Msg == WM_SYSKEYUP) && (int)m.WParam == VK_ALT; + if (!filterAltKeyToPreventFocusLoss) + base.WndProc(ref m); - ImGuiIOPtr io = ImGui.GetIO(); - switch (m.Msg) - { - - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - { - if (isViewer) - return; - - int button = 0; - if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONDBLCLK) button = 0; - if (m.Msg == WM_RBUTTONDOWN || m.Msg == WM_RBUTTONDBLCLK) button = 1; - if (m.Msg == WM_MBUTTONDOWN || m.Msg == WM_MBUTTONDBLCLK) button = 2; - // TODO - //if (!ImGui.IsAnyMouseDown() && ::GetCapture() == NULL) - // ::SetCapture(hwnd); - io.MouseDown[button] = true; + foreach (var inputMethod in InputMethods) + inputMethod.ProcessMessage(m); + + var isViewer = this == ProgramWindows.Viewer?.Form; + + ImGuiIOPtr io = ImGui.GetIO(); + if (KeyHandler.PressedKeys == null) return; - } - case WM_LBUTTONUP: - case WM_RBUTTONUP: - case WM_MBUTTONUP: + + switch (m.Msg) { - int button = 0; - if (m.Msg == WM_LBUTTONUP) button = 0; - if (m.Msg == WM_RBUTTONUP) button = 1; - if (m.Msg == WM_MBUTTONUP) button = 2; - io.MouseDown[button] = false; - // TODO - //if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) - // ::ReleaseCapture(); - return; - } - case WM_MOUSEWHEEL: - io.MouseWheel += (short)(((uint)(long)m.WParam >> 16) & 0xffff) / 120.0f; // TODO (float)WHEEL_DELTA; - return; - case WM_MOUSEHWHEEL: - io.MouseWheelH += (short)(((uint)(long)m.WParam >> 16) & 0xffff) / 120.0f; // TODO (float)WHEEL_DELTA; - return; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - switch ((int)m.WParam) + + case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: { - case VK_SHIFT: - io.KeyShift = true; - io.KeysDown[(int)m.WParam] = true; - io.KeysDown[(int)Key.ShiftKey] = true; - break; - case VK_CONTROL: - io.KeyCtrl = true; - io.KeysDown[(int)Key.CtrlKey] = true; - break; - case VK_ALT: - io.KeyAlt = true; - io.KeysDown[(int)Key.Alt] = true; - KeyHandler.PressedKeys[(int)Key.Alt] = true; - break; - default: + if (isViewer) + return; + + int button = 0; + if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONDBLCLK) button = 0; + if (m.Msg == WM_RBUTTONDOWN || m.Msg == WM_RBUTTONDBLCLK) button = 1; + if (m.Msg == WM_MBUTTONDOWN || m.Msg == WM_MBUTTONDBLCLK) button = 2; + // TODO + //if (!ImGui.IsAnyMouseDown() && ::GetCapture() == NULL) + // ::SetCapture(hwnd); + io.MouseDown[button] = true; + return; + } + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + { + int button = 0; + if (m.Msg == WM_LBUTTONUP) button = 0; + if (m.Msg == WM_RBUTTONUP) button = 1; + if (m.Msg == WM_MBUTTONUP) button = 2; + io.MouseDown[button] = false; + // TODO + //if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + // ::ReleaseCapture(); + return; + } + case WM_MOUSEWHEEL: + io.MouseWheel += (short)(((uint)(long)m.WParam >> 16) & 0xffff) / 120.0f; // TODO (float)WHEEL_DELTA; + return; + case WM_MOUSEHWHEEL: + io.MouseWheelH += (short)(((uint)(long)m.WParam >> 16) & 0xffff) / 120.0f; // TODO (float)WHEEL_DELTA; + return; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + switch ((int)m.WParam) { - if ((int)m.WParam < 256) + case VK_SHIFT: + io.KeyShift = true; io.KeysDown[(int)m.WParam] = true; - break; + io.KeysDown[(int)Key.ShiftKey] = true; + break; + case VK_CONTROL: + io.KeyCtrl = true; + io.KeysDown[(int)Key.CtrlKey] = true; + break; + case VK_ALT: + io.KeyAlt = true; + io.KeysDown[(int)Key.Alt] = true; + KeyHandler.PressedKeys[(int)Key.Alt] = true; + break; + default: + { + if ((int)m.WParam < 256) + io.KeysDown[(int)m.WParam] = true; + break; + } } - } - return; - case WM_KEYUP: - case WM_SYSKEYUP: - switch ((int)m.WParam) - { - case VK_SHIFT: - io.KeyShift = false; - io.KeysDown[(int)Key.ShiftKey] = false; - break; - case VK_CONTROL: - io.KeyCtrl = false; - io.KeysDown[(int)Key.CtrlKey] = false; - break; - case VK_ALT: - io.KeyAlt = false; - io.KeysDown[(int)Key.Alt] = false; - KeyHandler.PressedKeys[(int)Key.Alt] = false; - break; - default: + return; + case WM_KEYUP: + case WM_SYSKEYUP: + switch ((int)m.WParam) { - if ((int)m.WParam < 256) - io.KeysDown[(int)m.WParam] = false; - break; + case VK_SHIFT: + io.KeyShift = false; + io.KeysDown[(int)Key.ShiftKey] = false; + break; + case VK_CONTROL: + io.KeyCtrl = false; + io.KeysDown[(int)Key.CtrlKey] = false; + break; + case VK_ALT: + io.KeyAlt = false; + io.KeysDown[(int)Key.Alt] = false; + KeyHandler.PressedKeys[(int)Key.Alt] = false; + break; + default: + { + if ((int)m.WParam < 256) + io.KeysDown[(int)m.WParam] = false; + break; + } } - } - return; - case WM_CHAR: - // You can also use ToAscii()+GetKeyboardState() to retrieve characters. - if ((int)m.WParam > 0 && (int)m.WParam < 0x10000) - io.AddInputCharacter((ushort)m.WParam); - return; - case WM_SETCURSOR: - if ((((int)m.LParam & 0xFFFF) == 1) && UpdateMouseCursor()) - m.Result = (IntPtr)1; - return; - case WM_SETFOCUS: - for (int i = 0; i < io.KeysDown.Count; i++) - io.KeysDown[i] = false; - io.KeyShift = false; - io.KeyCtrl = false; - io.KeyAlt = false; - break; - - case WM_ACTIVATEAPP: - if (m.WParam.ToInt64() == 0) /* Being deactivated */ - { - io.KeysDown[(int)Key.Alt] = false; - KeyHandler.PressedKeys[(int)Key.Alt] = false; - } + return; + case WM_CHAR: + // You can also use ToAscii()+GetKeyboardState() to retrieve characters. + if ((int)m.WParam > 0 && (int)m.WParam < 0x10000) + io.AddInputCharacter((ushort)m.WParam); + return; + case WM_SETCURSOR: + if ((((int)m.LParam & 0xFFFF) == 1) && UpdateMouseCursor()) + m.Result = (IntPtr)1; + return; + case WM_SETFOCUS: + for (int i = 0; i < io.KeysDown.Count; i++) + io.KeysDown[i] = false; + io.KeyShift = false; + io.KeyCtrl = false; + io.KeyAlt = false; + break; - break; + case WM_ACTIVATEAPP: + if (m.WParam.ToInt64() == 0) /* Being deactivated */ + { + io.KeysDown[(int)Key.Alt] = false; + KeyHandler.PressedKeys[(int)Key.Alt] = false; + } + + break; + } + } + catch (NullReferenceException) + { + Log.Warning("Detected invalid event message that would trigger null-reference exception"); } } diff --git a/Editor/App/ProgramWindows.cs b/Editor/App/ProgramWindows.cs index 89cf3042aa..0cb8c0ef50 100644 --- a/Editor/App/ProgramWindows.cs +++ b/Editor/App/ProgramWindows.cs @@ -1,185 +1,199 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Windows.Forms; -using SharpDX; -using SharpDX.Direct3D; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using T3.Core.IO; -using T3.Core.Logging; -using T3.Core.Resource; -using T3.Editor.Gui; -using T3.Editor.Gui.UiHelpers; -using T3.Editor.SystemUi; -using T3.SystemUi; -using Device = SharpDX.Direct3D11.Device; - -namespace T3.Editor.App; - -internal static class ProgramWindows -{ - public static AppWindow Main { get; private set; } - public static AppWindow Viewer { get; private set; } // Required it distinguish 2nd render view in mouse handling - private static Device _device; - private static DeviceContext _deviceContext; - private static Factory _factory; - - internal static void SetMainWindowSize(int width, int height) - { - Main.SetSize(width, height); - Main.SetBorderStyleSizable(); - } - - internal static void SetInteractionDevices(params object[] objects) - { - IWindowsFormsMessageHandler[] messageHandlers = objects.OfType().ToArray(); - ImGuiDx11RenderForm.InputMethods = messageHandlers; - } - - public static void SetVertexShader(VertexShaderResource resource) => _deviceContext.VertexShader.Set(resource.VertexShader); - public static void SetPixelShader(PixelShaderResource resource) => _deviceContext.PixelShader.Set(resource.PixelShader); - - internal static void HandleFullscreenToggle() - { - if (Main.IsFullScreen == UserSettings.Config.FullScreen) - return; - - if (UserSettings.Config.FullScreen) - { - var screenCount = Screen.AllScreens.Length; - var hasSecondScreen = screenCount > 1; - var secondScreenIndex = hasSecondScreen ? 1 : 0; - - var screenIndexForMainScreen = UserSettings.Config.SwapMainAnd2ndWindowsWhenFullscreen ? secondScreenIndex : 0; - var screenIndexForSecondScreen = UserSettings.Config.SwapMainAnd2ndWindowsWhenFullscreen ? 0 : secondScreenIndex; - - Main.SetFullScreen(screenIndexForMainScreen); - Viewer.SetFullScreen(screenIndexForSecondScreen); - } - else - { - Main.SetSizeable(); - Viewer.SetSizeable(); - } - } - - internal static void InitializeMainWindow(string version, out Device device) - { - Main = new("T3 " + version, disableClose: false); - device = null; - - try - { - // Create Device and SwapChain - Device.CreateWithSwapChain(DriverType.Hardware, - DeviceCreationFlags.Debug, - Main.SwapChainDescription, - out device, - out var swapchain); - - _device = device; - _deviceContext = device.ImmediateContext; - _factory = swapchain.GetParent(); - - Main.SetDevice(device, _deviceContext, swapchain); - - Main.InitializeWindow(FormWindowState.Maximized, HandleKeyDown, HandleKeyUp, OnCloseMainWindow); - - // Ignore all windows events - _factory.MakeWindowAssociation(Main.HwndHandle, WindowAssociationFlags.IgnoreAll); - } - catch (Exception e) - { - EditorUi.Instance.ShowMessageBox("We are sorry but your graphics hardware might not be capable of running Tooll2\n\n" +e.Message, "Oh noooo", PopUpButtons.Ok); - Environment.Exit(0); - } - } - - internal static void InitializeSecondaryViewerWindow(string name, int width, int height) - { - Viewer = new(name, disableClose: true); - Viewer.SetDevice(_device, _deviceContext); - Viewer.SetSize(width, height); - Viewer.SetSizeable(); - Viewer.InitViewSwapChain(_factory); - Viewer.InitializeWindow(FormWindowState.Normal, null, null, null); - Viewer.Show(); - } - - private static void OnCloseMainWindow(object sender, CancelEventArgs args) - { - if (T3Ui.UiSymbolData.IsSaving) - { - args.Cancel = true; - Log.Debug($"Cancel closing because save-operation is in progress."); - } - else - { - Log.Debug("Shutting down"); - } - } - - private static void HandleKeyDown(object sender, KeyEventArgs e) - { - var keyIndex = (int)e.KeyCode; - if (keyIndex >= KeyHandler.PressedKeys.Length) - { - Log.Warning($"Ignoring out of range key code {e.KeyCode} with index {keyIndex}"); - } - else - { - KeyHandler.PressedKeys[keyIndex] = true; - } - } - - private static void HandleKeyUp(object sender, KeyEventArgs e) - { - var keyIndex = (int)e.KeyCode; - if (keyIndex < KeyHandler.PressedKeys.Length) - { - KeyHandler.PressedKeys[keyIndex] = false; - } - } - - public static void Release() - { - Main.Release(); - Viewer.Release(); - _device.ImmediateContext.ClearState(); - _deviceContext.Flush(); - _device.Dispose(); - _deviceContext.Dispose(); - _factory.Dispose(); - } - - public static void SetRasterizerState(RasterizerState viewWindowRasterizerState) - { - _deviceContext.Rasterizer.State = viewWindowRasterizerState; - } - - public static void SetPixelShaderResource(ShaderResourceView viewWindowBackgroundSrv) - { - _deviceContext.PixelShader.SetShaderResource(0, viewWindowBackgroundSrv); - } - - public static void CopyToSecondaryRenderOutput() - { - _deviceContext.Draw(3, 0); - _deviceContext.PixelShader.SetShaderResource(0, null); - } - - public static void RefreshViewport() - { - _deviceContext.Rasterizer.SetViewport(new Viewport(0, 0, Main.Width, Main.Height, 0.0f, 1.0f)); - _deviceContext.OutputMerger.SetTargets(Main.RenderTargetView); - } - - public static void Present(bool useVSync, bool showSecondaryRenderWindow) - { - Main.SwapChain.Present(useVSync ? 1 : 0, PresentFlags.None); - - if (showSecondaryRenderWindow) - Viewer.SwapChain.Present(useVSync ? 1 : 0, PresentFlags.None); - } +using System; +using System.ComponentModel; +using System.Linq; +using System.Windows.Forms; +using SharpDX; +using SharpDX.Direct3D; +using SharpDX.Direct3D11; +using SharpDX.DXGI; +using T3.Core.IO; +using T3.Core.Logging; +using T3.Core.Resource; +using T3.Editor.Gui; +using T3.Editor.Gui.Interaction.StartupCheck; +using T3.Editor.Gui.UiHelpers; +using T3.Editor.SystemUi; +using T3.SystemUi; +using Device = SharpDX.Direct3D11.Device; + +namespace T3.Editor.App; + +internal static class ProgramWindows +{ + public static AppWindow Main { get; private set; } + public static AppWindow Viewer { get; private set; } // Required it distinguish 2nd render view in mouse handling + private static Device _device; + private static DeviceContext _deviceContext; + private static Factory _factory; + + internal static void SetMainWindowSize(int width, int height) + { + Main.SetSize(width, height); + Main.SetBorderStyleSizable(); + } + + internal static void SetInteractionDevices(params object[] objects) + { + IWindowsFormsMessageHandler[] messageHandlers = objects.OfType().ToArray(); + ImGuiDx11RenderForm.InputMethods = messageHandlers; + } + + public static void SetVertexShader(VertexShaderResource resource) => _deviceContext.VertexShader.Set(resource.VertexShader); + public static void SetPixelShader(PixelShaderResource resource) => _deviceContext.PixelShader.Set(resource.PixelShader); + + internal static void HandleFullscreenToggle() + { + if (Main.IsFullScreen == UserSettings.Config.FullScreen) + return; + + if (UserSettings.Config.FullScreen) + { + var screenCount = Screen.AllScreens.Length; + Main.SetFullScreen(UserSettings.Config.FullScreenIndexMain < screenCount ? UserSettings.Config.FullScreenIndexMain : 0); + Viewer.SetFullScreen(UserSettings.Config.FullScreenIndexViewer < screenCount ? UserSettings.Config.FullScreenIndexViewer : 0); + } + else + { + Main.SetSizeable(); + Viewer.SetSizeable(); + } + } + + internal static void InitializeMainWindow(string version, out Device device) + { + Main = new("T3 " + version, disableClose: false); + device = null; + + try + { + // Create Device and SwapChain + Device.CreateWithSwapChain(DriverType.Hardware, + DeviceCreationFlags.Debug, + Main.SwapChainDescription, + out device, + out var swapchain); + + _device = device; + _deviceContext = device.ImmediateContext; + _factory = swapchain.GetParent(); + + Main.SetDevice(device, _deviceContext, swapchain); + + Main.InitializeWindow(FormWindowState.Maximized, HandleKeyDown, HandleKeyUp, OnCloseMainWindow); + + // Ignore all windows events + _factory.MakeWindowAssociation(Main.HwndHandle, WindowAssociationFlags.IgnoreAll); + } + catch (Exception e) + { + if (e.Message.Contains("DXGI_ERROR_SDK_COMPONENT_MISSING")) + { + var result = EditorUi.Instance.ShowMessageBox("You need to install Windows Graphics diagnostics tools.\n\nClick Ok to download this Windows component directly from Microsoft.", "Windows component missing", PopUpButtons.OkCancel); + if (result == PopUpResult.Ok) + { + StartupValidation.OpenUrl("https://learn.microsoft.com/en-us/windows/uwp/gaming/use-the-directx-runtime-and-visual-studio-graphics-diagnostic-features"); + } + } + else + { + EditorUi.Instance.ShowMessageBox("We are sorry but your graphics hardware might not be capable of running Tooll2\n\n" +e.Message, "Oh noooo", PopUpButtons.Ok); + } + Environment.Exit(0); + } + } + + internal static void InitializeSecondaryViewerWindow(string name, int width, int height) + { + Viewer = new(name, disableClose: true); + Viewer.SetDevice(_device, _deviceContext); + Viewer.SetSize(width, height); + Viewer.SetSizeable(); + Viewer.InitViewSwapChain(_factory); + Viewer.InitializeWindow(FormWindowState.Normal, null, null, null); + Viewer.Show(); + } + + private static void OnCloseMainWindow(object sender, CancelEventArgs args) + { + if (T3Ui.UiSymbolData.IsSaving) + { + args.Cancel = true; + Log.Debug($"Cancel closing because save-operation is in progress."); + } + else + { + Log.Debug("Shutting down"); + } + } + + private static void HandleKeyDown(object sender, KeyEventArgs e) + { + var keyIndex = (int)e.KeyCode; + if (keyIndex >= KeyHandler.PressedKeys.Length) + { + Log.Warning($"Ignoring out of range key code {e.KeyCode} with index {keyIndex}"); + } + else + { + KeyHandler.PressedKeys[keyIndex] = true; + } + } + + private static void HandleKeyUp(object sender, KeyEventArgs e) + { + var keyIndex = (int)e.KeyCode; + if (keyIndex < KeyHandler.PressedKeys.Length) + { + KeyHandler.PressedKeys[keyIndex] = false; + } + } + + public static void Release() + { + Main.Release(); + Viewer.Release(); + _device.ImmediateContext.ClearState(); + _deviceContext.Flush(); + _device.Dispose(); + _deviceContext.Dispose(); + _factory.Dispose(); + } + + public static void SetRasterizerState(RasterizerState viewWindowRasterizerState) + { + _deviceContext.Rasterizer.State = viewWindowRasterizerState; + } + + public static void SetPixelShaderResource(ShaderResourceView viewWindowBackgroundSrv) + { + _deviceContext.PixelShader.SetShaderResource(0, viewWindowBackgroundSrv); + } + + public static void CopyToSecondaryRenderOutput() + { + _deviceContext.Draw(3, 0); + _deviceContext.PixelShader.SetShaderResource(0, null); + } + + public static void RefreshViewport() + { + _deviceContext.Rasterizer.SetViewport(new Viewport(0, 0, Main.Width, Main.Height, 0.0f, 1.0f)); + _deviceContext.OutputMerger.SetTargets(Main.RenderTargetView); + } + + public static void Present(bool useVSync, bool showSecondaryRenderWindow) + { + try + { + Main.SwapChain.Present(useVSync ? 1 : 0, PresentFlags.None); + + if (showSecondaryRenderWindow) + Viewer.SwapChain.Present(useVSync ? 1 : 0, PresentFlags.None); + } + catch (SharpDX.SharpDXException) + { + var suspendReason = _device.DeviceRemovedReason.ToString(); + throw (new ApplicationException($"Graphics card suspended ({suspendReason})")); + } + } } \ No newline at end of file diff --git a/Editor/Compilation/OperatorUpdating.cs b/Editor/Compilation/OperatorUpdating.cs index 52b42700d5..61439e8f9d 100644 --- a/Editor/Compilation/OperatorUpdating.cs +++ b/Editor/Compilation/OperatorUpdating.cs @@ -94,15 +94,23 @@ public static Assembly CompileSymbolFromSource(string source, string symbolName) } else { - Log.Info($"Compilation of '{symbolName}' successful."); - var newAssembly = Assembly.Load(dllStream.GetBuffer()); - if (newAssembly.ExportedTypes.Any()) + try { - return newAssembly; + var newAssembly = Assembly.Load(dllStream.GetBuffer()); + if (newAssembly.ExportedTypes.Any()) + { + Log.Info($"Compilation of '{symbolName}' successful."); + return newAssembly; + } + else + { + Log.Error("New compiled assembly had no exported type."); + return null; + } } - else + catch (Exception e) { - Log.Error("New compiled assembly had no exported type."); + Log.Error("Failed to load compiled type: " + e.Message); return null; } } diff --git a/Editor/CrashReporting.cs b/Editor/CrashReporting.cs new file mode 100644 index 0000000000..5b14f204a8 --- /dev/null +++ b/Editor/CrashReporting.cs @@ -0,0 +1,92 @@ +using System; +using System.Linq; +using System.Windows.Forms; +using Sentry; +using T3.Core.Animation; +using T3.Editor.Gui; +using T3.Editor.Gui.AutoBackup; +using T3.Editor.Gui.Commands; +using T3.Editor.Gui.Graph; +using T3.Editor.Gui.Graph.Interaction; +using T3.Editor.Gui.Graph.Modification; +using T3.Editor.Gui.UiHelpers; +using T3.Editor.SystemUi; +using T3.Editor.UiModel; + +namespace T3.Editor; + +internal static class CrashReporting +{ + public static void InitializeCrashReporting() + { + SentrySdk.Init(o => + { + // Tells which project in Sentry to send events to: + o.Dsn = "https://52e37e10dc9cebcc2328cc63fab57211@o4505681078059008.ingest.sentry.io/4505681082384384"; + o.Debug = false; + o.TracesSampleRate = 0.0; + o.IsGlobalModeEnabled = true; + o.SendClientReports = false; + o.AutoSessionTracking = false; + o.SendDefaultPii = false; + o.Release = Program.GetReleaseVersion(indicateDebugBuild: false); + o.SetBeforeSend((Func)CrashHandler); + }); + + SentrySdk.ConfigureScope(scope => { scope.SetTag("IsStandAlone", Program.IsStandAlone ? "Yes" : "No"); }); + + var configuration = "Release"; + #if DEBUG + configuration = "Debug"; + #endif + + SentrySdk.ConfigureScope(scope => { scope.SetTag("Configuration", configuration); }); + + // Configure WinForms to throw exceptions so Sentry can capture them. + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException); + } + + private static SentryEvent CrashHandler(SentryEvent sentryEvent, Hint hint) + { + var timeOfLastBackup = AutoBackup.GetTimeOfLastBackup(); + var timeSpan = THelpers.GetReadableRelativeTime(timeOfLastBackup); + + var result = MessageBox.Show(string.Join("\n", + "Oh noooo, how embarrassing! T3 just crashed.", + $"Last backup was saved {timeSpan} to .t3/backups/", + "We copied the current operator to your clipboard.", + "Check the FAQ on what to do next.", + "", + "Click Yes to send a crash report to tooll.sentry.io.", + "This will hopefully help us to fix this issue." + ), + @"☠🙈 Damn!", + MessageBoxButtons.YesNo); + + SentrySdk.ConfigureScope(scope => { scope.SetTag("IsStandAlone", Program.IsStandAlone ? "Yes" : "No"); }); + sentryEvent.SetExtra("UndoStack", UndoRedoStack.GetUndoStackAsString()); + sentryEvent.SetExtra("Selection", string.Join("\n", NodeSelection.Selection)); + sentryEvent.SetExtra("Nickname", UserSettings.Config.UserName); + sentryEvent.SetExtra("Runtime", Playback.RunTimeInSecs); + + try + { + var primaryComposition = GraphWindow.GetMainComposition(); + if (primaryComposition != null) + { + var compositionUi = SymbolUiRegistry.Entries[primaryComposition.Symbol.Id]; + var json = GraphOperations.CopyNodesAsJson( + primaryComposition.Symbol.Id, + compositionUi.ChildUis, + compositionUi.Annotations.Values.ToList()); + EditorUi.Instance.SetClipboardText(json); + } + } + catch (Exception e) + { + sentryEvent.SetExtra("CurrentOpExportFailed", e.Message); + } + + return result == DialogResult.Yes ? sentryEvent : null; + } +} \ No newline at end of file diff --git a/Editor/Gui/ChildUi/AStringUi.cs b/Editor/Gui/ChildUi/AStringUi.cs index 43e3540219..6253145364 100644 --- a/Editor/Gui/ChildUi/AStringUi.cs +++ b/Editor/Gui/ChildUi/AStringUi.cs @@ -2,10 +2,12 @@ using ImGuiNET; using T3.Core.Logging; using T3.Core.Operator; +using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Graph; using T3.Editor.Gui.InputUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using String = T3.Operators.Types.Id_5880cbc3_a541_4484_a06a_0e6f77cdbe8e.AString; namespace T3.Editor.Gui.ChildUi @@ -30,7 +32,9 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw if (stringInstance.InputString.IsConnected) return SymbolChildUi.CustomUiResult.None; + var dragWidth = WidgetElements.DrawDragIndicator(screenRect, drawList); var usableArea = screenRect; + usableArea.Min.X += dragWidth; ImGui.PushID(instance.SymbolChildId.GetHashCode()); diff --git a/Editor/Gui/ChildUi/AnimValueUi.cs b/Editor/Gui/ChildUi/AnimValueUi.cs index 9d598b71fa..bc0872df8d 100644 --- a/Editor/Gui/ChildUi/AnimValueUi.cs +++ b/Editor/Gui/ChildUi/AnimValueUi.cs @@ -6,6 +6,7 @@ using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_ea7b8491_2f8e_4add_b0b1_fd068ccfed0d; namespace T3.Editor.Gui.ChildUi @@ -89,7 +90,11 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw DrawCurve(drawList, graphRect, animValue, highlightEditable); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; + } private static void DrawCurve(ImDrawListPtr drawList, ImRect graphRect, AnimValue animValue, bool highlightEditable) @@ -97,6 +102,12 @@ private static void DrawCurve(ImDrawListPtr drawList, ImRect graphRect, AnimValu var graphWidth = graphRect.GetWidth(); var h = graphRect.GetHeight(); + var shapeIndex = (animValue.Shape.IsConnected) // Todo check for animated + ? animValue.Shape.Value + :animValue.Shape.TypedInputValue.Value; + + var shape = (AnimMath.Shapes)shapeIndex.Clamp(0, Enum.GetNames(typeof(AnimMath.Shapes)).Length); + // Draw Graph { const float previousCycleFragment = 0.25f; @@ -131,7 +142,7 @@ private static void DrawCurve(ImDrawListPtr drawList, ImRect graphRect, AnimValu var f = (float)i / GraphListSteps; var fragment = f * (1 + previousCycleFragment) - previousCycleFragment + Math.Floor(animValue._normalizedTime); - var v = AnimMath.CalcValueForNormalizedTime(animValue._shape, + var v = AnimMath.CalcValueForNormalizedTime(shape, fragment, 0, animValue.Bias.TypedInputValue.Value, diff --git a/Editor/Gui/ChildUi/AnimVec2Ui.cs b/Editor/Gui/ChildUi/AnimVec2Ui.cs index f73a21148a..eb9b2412d9 100644 --- a/Editor/Gui/ChildUi/AnimVec2Ui.cs +++ b/Editor/Gui/ChildUi/AnimVec2Ui.cs @@ -6,6 +6,7 @@ using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_af79ee8c_d08d_4dca_b478_b4542ed69ad8; namespace T3.Editor.Gui.ChildUi @@ -86,7 +87,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw DrawCurve(drawList, graphRect, animVec2, highlightEditable); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } private static void DrawCurve(ImDrawListPtr drawList, ImRect graphRect, AnimVec2 animValue, bool highlightEditable) diff --git a/Editor/Gui/ChildUi/AnimVec3Ui.cs b/Editor/Gui/ChildUi/AnimVec3Ui.cs index d3cac17dca..ab51cd524e 100644 --- a/Editor/Gui/ChildUi/AnimVec3Ui.cs +++ b/Editor/Gui/ChildUi/AnimVec3Ui.cs @@ -6,6 +6,7 @@ using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_7814fd81_b8d0_4edf_b828_5165f5657344; namespace T3.Editor.Gui.ChildUi @@ -82,7 +83,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw DrawCurve(drawList, graphRect, animVec2, highlightEditable); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } private static void DrawCurve(ImDrawListPtr drawList, ImRect graphRect, AnimVec3 animValue, bool highlightEditable) diff --git a/Editor/Gui/ChildUi/AudioReactionUi.cs b/Editor/Gui/ChildUi/AudioReactionUi.cs index f8151d28e0..f09053bd75 100644 --- a/Editor/Gui/ChildUi/AudioReactionUi.cs +++ b/Editor/Gui/ChildUi/AudioReactionUi.cs @@ -6,6 +6,7 @@ using T3.Core.Utils; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_03477b9a_860e_4887_81c3_5fe51621122c; namespace T3.Editor.Gui.ChildUi @@ -183,7 +184,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw drawList.PopClipRect(); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } diff --git a/Editor/Gui/ChildUi/BooleanUi.cs b/Editor/Gui/ChildUi/BooleanUi.cs index 11807a9787..ea45270242 100644 --- a/Editor/Gui/ChildUi/BooleanUi.cs +++ b/Editor/Gui/ChildUi/BooleanUi.cs @@ -1,11 +1,14 @@ -using System.Linq; +using System; +using System.Linq; using System.Numerics; using ImGuiNET; using T3.Core.Operator; +using T3.Editor.Gui.ChildUi.WidgetUi; +using T3.Editor.Gui.Graph; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; -using T3.Operators.Types.Id_ed0f5188_8888_453e_8db4_20d87d18e9f4; -using Icon = T3.Editor.Gui.Styling.Icon; +using T3.Editor.UiModel; +using Boolean = T3.Operators.Types.Id_ed0f5188_8888_453e_8db4_20d87d18e9f4.Boolean; namespace T3.Editor.Gui.ChildUi { @@ -13,38 +16,118 @@ public static class BooleanUi { public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDrawListPtr drawList, ImRect screenRect) { - if (!(instance is Boolean boolean) - || !ImGui.IsRectVisible(screenRect.Min, screenRect.Max)) + if (instance is not Boolean boolean) return SymbolChildUi.CustomUiResult.None; - ImGui.PushID(instance.SymbolChildId.GetHashCode()); + if (!ImGui.IsRectVisible(screenRect.Min, screenRect.Max)) + return SymbolChildUi.CustomUiResult.None; + + var dragWidth = WidgetElements.DrawDragIndicator(screenRect, drawList); + var colorAsVec4 = boolean.ColorInGraph.TypedInputValue.Value; + var color = new Color(colorAsVec4); + + var activeRect = screenRect; + activeRect.Min.X += dragWidth; - ImGui.SetCursorScreenPos(screenRect.Min + new Vector2(2, 2)); + ImGui.PushID(instance.SymbolChildId.GetHashCode()); + screenRect.Expand(-4); + ImGui.SetCursorScreenPos(screenRect.Min); var symbolChild = instance.Parent.Symbol.Children.Single(c => c.Id == instance.SymbolChildId); ImGui.PushClipRect(screenRect.Min, screenRect.Max, true); - var refValue = boolean.BoolValue.Value; // we reference here to show correct state when connected + var refValue = boolean.BoolValue.Value; + var label = string.IsNullOrEmpty(symbolChild.Name) + ? (refValue ? "True" : "False") + : symbolChild.ReadableName; + + drawList.AddRectFilled(activeRect.Min, activeRect.Max, color.Fade(refValue ? 0.5f : 0.1f)); + var canvasScale = GraphCanvas.Current.Scale.Y; + + var font = WidgetElements.GetPrimaryLabelFont(canvasScale); + var labelColor = WidgetElements.GetPrimaryLabelColor(canvasScale); + + ImGui.PushFont(font); + var labelSize = ImGui.CalcTextSize(label); + + var labelPos = new Vector2(activeRect.Min.X + 18 * canvasScale, + (activeRect.Min.Y + activeRect.Max.Y) / 2 - labelSize.Y / 2); + drawList.AddText(font, font.FontSize, labelPos, labelColor, label); + ImGui.PopFont(); - if (CustomComponents.ToggleIconButton(Icon.Checkmark, "", ref refValue, new Vector2(20, 20))) + var checkCenter = new Vector2(labelPos.X - 10f * canvasScale, + (activeRect.Min.Y + activeRect.Max.Y) / 2 + 1.5f * canvasScale + ); + var checkSize = MathF.Min(100, 2.5f * canvasScale); + var points = new[] + { + checkCenter + new Vector2(-2, -1) * checkSize, + checkCenter + new Vector2(0, 1) * checkSize, + checkCenter + new Vector2(3, -2) * checkSize, + }; + drawList.AddPolyline(ref points[0], 3, + refValue ? UiColors.WidgetTitle : UiColors.BackgroundFull.Fade(0.2f), + ImDrawFlags.None, + MathF.Max(1.4f, 0.5f * canvasScale)); + + if (!boolean.BoolValue.IsConnected) { - if (!boolean.BoolValue.IsConnected) + var isHoveredOrActive = boolean.SymbolChildId == activeInputId || + ImGui.IsWindowHovered() && activeRect.Contains(ImGui.GetMousePos()); + if (isHoveredOrActive) { - boolean.BoolValue.TypedInputValue.Value = !boolean.BoolValue.TypedInputValue.Value; + if (ImGui.IsMouseClicked(ImGuiMouseButton.Left)) + { + activeInputId = boolean.SymbolChildId; + } + else if (ImGui.IsMouseReleased(ImGuiMouseButton.Left) && ImGui.GetMouseDragDelta().LengthSquared() < UserSettings.Config.ClickThreshold) + { + activeInputId = Guid.Empty; + var newValue = !boolean.BoolValue.TypedInputValue.Value; + boolean.BoolValue.SetTypedInputValue(newValue); + } } - - boolean.BoolValue.Input.IsDefault = false; - boolean.BoolValue.DirtyFlag.Invalidate(); } - ImGui.SameLine(); - var label = string.IsNullOrEmpty(symbolChild.Name) - ? refValue ? "True" : "False" - : symbolChild.ReadableName; - ImGui.TextUnformatted(label); - ImGui.PopClipRect(); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventTooltip + | SymbolChildUi.CustomUiResult.PreventOpenParameterPopUp + | SymbolChildUi.CustomUiResult.PreventInputLabels; } + + /// + /// toggle button for boolean math op + /// + private static bool ToggleButtonB(string label, ref bool isSelected, Vector2 size, Vector4 color, bool trigger = false) + { + var clicked = false; + var colorInactive = color - new Vector4(.0f, .0f, .0f, .3f); + + ImGui.PushFont(GraphCanvas.Current.Scale.X < 2 + ? Fonts.FontSmall + : GraphCanvas.Current.Scale.X < 4 + ? Fonts.FontNormal + : Fonts.FontLarge); + + ImGui.PushStyleColor(ImGuiCol.Button, isSelected ? color : colorInactive); + ImGui.PushStyleColor(ImGuiCol.ButtonHovered, color); // Adjust this as needed + ImGui.PushStyleColor(ImGuiCol.ButtonActive, colorInactive); // Adjust this as needed + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.Selection.Rgba); + + if (ImGui.Button(label, size) || trigger) + { + isSelected = !isSelected; + clicked = true; + } + + ImGui.PopStyleColor(4); + ImGui.PopFont(); + + return clicked; + } + + private static Guid activeInputId; } } \ No newline at end of file diff --git a/Editor/Gui/ChildUi/CounterUi.cs b/Editor/Gui/ChildUi/CounterUi.cs index c68e1ba16e..457394691c 100644 --- a/Editor/Gui/ChildUi/CounterUi.cs +++ b/Editor/Gui/ChildUi/CounterUi.cs @@ -2,6 +2,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_11882635_4757_4cac_a024_70bb4e8b504c; namespace T3.Editor.Gui.ChildUi @@ -40,7 +41,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw } ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } } } \ No newline at end of file diff --git a/Editor/Gui/ChildUi/CustomChildUiRegistry.cs b/Editor/Gui/ChildUi/CustomChildUiRegistry.cs index e82925df99..d06f891f9d 100644 --- a/Editor/Gui/ChildUi/CustomChildUiRegistry.cs +++ b/Editor/Gui/ChildUi/CustomChildUiRegistry.cs @@ -3,6 +3,7 @@ using ImGuiNET; using T3.Core.Operator; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.ChildUi { diff --git a/Editor/Gui/ChildUi/DataListUi.cs b/Editor/Gui/ChildUi/DataListUi.cs index 50fc827c45..cc4ac18eec 100644 --- a/Editor/Gui/ChildUi/DataListUi.cs +++ b/Editor/Gui/ChildUi/DataListUi.cs @@ -2,6 +2,7 @@ using T3.Core.Operator; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_bfe540ef_f8ad_45a2_b557_cd419d9c8e44; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/DescriptiveUi.cs b/Editor/Gui/ChildUi/DescriptiveUi.cs index 5aa2acf1c0..55b0a1d9d0 100644 --- a/Editor/Gui/ChildUi/DescriptiveUi.cs +++ b/Editor/Gui/ChildUi/DescriptiveUi.cs @@ -7,6 +7,7 @@ using T3.Core.Operator.Interfaces; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.ChildUi { diff --git a/Editor/Gui/ChildUi/GetFloatVarUi.cs b/Editor/Gui/ChildUi/GetFloatVarUi.cs index 3161acca5c..a48f5770a2 100644 --- a/Editor/Gui/ChildUi/GetFloatVarUi.cs +++ b/Editor/Gui/ChildUi/GetFloatVarUi.cs @@ -3,6 +3,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_e6072ecf_30d2_4c52_afa1_3b195d61617b; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/GetIntVarUi.cs b/Editor/Gui/ChildUi/GetIntVarUi.cs index dac67300a3..54196e91c5 100644 --- a/Editor/Gui/ChildUi/GetIntVarUi.cs +++ b/Editor/Gui/ChildUi/GetIntVarUi.cs @@ -3,6 +3,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_470db771_c7f2_4c52_8897_d3a9b9fc6a4e; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/GpuMeasureUi.cs b/Editor/Gui/ChildUi/GpuMeasureUi.cs index 0e5a834c22..c7564349ef 100644 --- a/Editor/Gui/ChildUi/GpuMeasureUi.cs +++ b/Editor/Gui/ChildUi/GpuMeasureUi.cs @@ -4,6 +4,7 @@ using T3.Core.Operator; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_000e08d0_669f_48df_9083_7aa0a43bbc05; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/GradientSliderUi.cs b/Editor/Gui/ChildUi/GradientSliderUi.cs index b21fa26498..465c96c5b9 100644 --- a/Editor/Gui/ChildUi/GradientSliderUi.cs +++ b/Editor/Gui/ChildUi/GradientSliderUi.cs @@ -2,8 +2,10 @@ using ImGuiNET; using T3.Core.Operator; using T3.Core.Utils; +using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_8211249d_7a26_4ad0_8d84_56da72a5c536; namespace T3.Editor.Gui.ChildUi @@ -12,38 +14,46 @@ public static class GradientSliderUi { public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDrawListPtr drawList, ImRect selectableScreenRect) { - if (!(instance is SampleGradient gradientSlider) + if (instance is not SampleGradient gradientInstance || !ImGui.IsRectVisible(selectableScreenRect.Min, selectableScreenRect.Max)) return SymbolChildUi.CustomUiResult.None; + var dragWidth = WidgetElements.DrawDragIndicator(selectableScreenRect, drawList); var innerRect = selectableScreenRect; - innerRect.Expand(-7); - - var gradient = gradientSlider.Gradient.Value; - if (gradient == null) - { - //Log.Warning("Can't draw undefined gradient"); - return SymbolChildUi.CustomUiResult.None; - } - - var cloneIfModified = gradientSlider.Gradient.Input.IsDefault; + innerRect.Min.X += dragWidth; + + var gradient = (gradientInstance.Gradient.IsConnected) + ? gradientInstance.Gradient.Value + :gradientInstance.Gradient.TypedInputValue.Value; - if (GradientEditor.Draw(ref gradient, drawList, innerRect, cloneIfModified)) + if (gradient != null) { - if (cloneIfModified) + //Log.Warning("Can't draw undefined gradient"); + var cloneIfModified = gradientInstance.Gradient.Input.IsDefault; + + if (GradientEditor.Draw(ref gradient, drawList, innerRect, cloneIfModified)) { - gradientSlider.Gradient.SetTypedInputValue(gradient); + if (cloneIfModified) + { + gradientInstance.Gradient.SetTypedInputValue(gradient); + } + gradientInstance.Color.DirtyFlag.Invalidate(); + gradientInstance.OutGradient.DirtyFlag.Invalidate(); } - gradientSlider.Color.DirtyFlag.Invalidate(); - gradientSlider.OutGradient.DirtyFlag.Invalidate(); + + var x = gradientInstance.SamplePos.Value.Clamp(0, 1) * innerRect.GetWidth(); + var pMin = new Vector2(innerRect.Min.X + x, innerRect.Min.Y); + var pMax = new Vector2(innerRect.Min.X + x + 2, innerRect.Max.Y); + drawList.AddRectFilled(pMin, pMax, UiColors.StatusAnimated); + //return SymbolChildUi.CustomUiResult.None; } - var x = gradientSlider.SamplePos.Value.Clamp(0, 1) * innerRect.GetWidth(); - var pMin = new Vector2(innerRect.Min.X + x, innerRect.Min.Y); - var pMax = new Vector2(innerRect.Min.X + x + 2, innerRect.Max.Y); - drawList.AddRectFilled(pMin, pMax, UiColors.StatusAnimated); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph | SymbolChildUi.CustomUiResult.PreventTooltip | SymbolChildUi.CustomUiResult.PreventOpenParameterPopUp; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventTooltip + | SymbolChildUi.CustomUiResult.PreventOpenParameterPopUp; } } } \ No newline at end of file diff --git a/Editor/Gui/ChildUi/IntValueUi.cs b/Editor/Gui/ChildUi/IntValueUi.cs index fc7fda6ec3..5bd5d41d7d 100644 --- a/Editor/Gui/ChildUi/IntValueUi.cs +++ b/Editor/Gui/ChildUi/IntValueUi.cs @@ -4,6 +4,7 @@ using T3.Core.Operator; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_cc07b314_4582_4c2c_84b8_bb32f59fc09b; namespace T3.Editor.Gui.ChildUi @@ -33,12 +34,21 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw ImGui.TextUnformatted(symbolChild.Name); } - ImGui.TextUnformatted($"{intValueInstance.Int.TypedInputValue.Value:0}"); + var isAnimated = instance.Parent?.Symbol.Animator.IsInputSlotAnimated(intValueInstance.Int)??false; + + var value = (isAnimated || intValueInstance.Int.IsConnected) + ? intValueInstance.Int.Value + : intValueInstance.Int.TypedInputValue.Value; + + ImGui.TextUnformatted($"{value:0}"); ImGui.EndGroup(); ImGui.PopFont(); ImGui.PopClipRect(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } } } \ No newline at end of file diff --git a/Editor/Gui/ChildUi/MidiInputUi.cs b/Editor/Gui/ChildUi/MidiInputUi.cs index 7faa40a617..737fae3efe 100644 --- a/Editor/Gui/ChildUi/MidiInputUi.cs +++ b/Editor/Gui/ChildUi/MidiInputUi.cs @@ -7,6 +7,7 @@ using T3.Core.Utils; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_59a0458e_2f3a_4856_96cd_32936f783cc5; namespace T3.Editor.Gui.ChildUi @@ -81,7 +82,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw ImGui.PopFont(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } } } diff --git a/Editor/Gui/ChildUi/RemapUi.cs b/Editor/Gui/ChildUi/RemapUi.cs index 082a5af762..27886660b3 100644 --- a/Editor/Gui/ChildUi/RemapUi.cs +++ b/Editor/Gui/ChildUi/RemapUi.cs @@ -5,6 +5,7 @@ using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_f0acd1a4_7a98_43ab_a807_6d1bd3e92169; using Vector2 = System.Numerics.Vector2; @@ -98,7 +99,7 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw ); drawList.PopClipRect(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph; + return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph | SymbolChildUi.CustomUiResult.PreventTooltip; } private const float TriangleSize = 4; diff --git a/Editor/Gui/ChildUi/SampleCurveUi.cs b/Editor/Gui/ChildUi/SampleCurveUi.cs index 97ebdfcb92..35b50ff81a 100644 --- a/Editor/Gui/ChildUi/SampleCurveUi.cs +++ b/Editor/Gui/ChildUi/SampleCurveUi.cs @@ -1,10 +1,13 @@ using System.Numerics; using ImGuiNET; using T3.Core.Operator; +using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.InputUi; using T3.Editor.Gui.InputUi.CombinedInputs; +using T3.Editor.Gui.Interaction; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_b724ea74_d5d7_4928_9cd1_7a7850e4e179; namespace T3.Editor.Gui.ChildUi @@ -15,18 +18,23 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw { if (!(instance is SampleCurve sampleCurve)) return SymbolChildUi.CustomUiResult.None; - + + var dragWidth = WidgetElements.DrawDragIndicator(selectableScreenRect, drawList); var innerRect = selectableScreenRect; - innerRect.Expand(-7); - + innerRect.Min.X += dragWidth; + innerRect.Min.Y += 1; + if (innerRect.GetHeight() < 0) return SymbolChildUi.CustomUiResult.PreventTooltip | SymbolChildUi.CustomUiResult.PreventOpenSubGraph | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenParameterPopUp; + var curve = (sampleCurve.Curve.IsConnected) + ? sampleCurve.Curve.Value + :sampleCurve.Curve.TypedInputValue.Value; - var curve = sampleCurve.Curve.Value; + //var curve = sampleCurve.Curve.Value; if (curve == null) { //Log.Warning("Can't draw undefined gradient"); @@ -37,8 +45,8 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw } ImGui.PushClipRect(innerRect.Min, innerRect.Max, true); - ImGui.SetCursorScreenPos(innerRect.Min); - ImGui.BeginChild("curve" + instance.SymbolChildId.GetHashCode(), innerRect.GetSize()); + ImGui.SetCursorScreenPos(innerRect.Min) ; + ImGui.BeginChild("curve" + instance.SymbolChildId.GetHashCode(), innerRect.GetSize(), false, ImGuiWindowFlags.NoScrollbar); { var cloneIfModified = sampleCurve.Curve.Input.IsDefault; @@ -46,6 +54,7 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw ? T3Ui.EditingFlags.None : T3Ui.EditingFlags.PreventMouseInteractions; + var keepPositionForIcon = ImGui.GetCursorPos() + Vector2.One; var modified2 = CurveInputEditing.DrawCanvasForCurve(ref curve, sampleCurve.Curve.Input, cloneIfModified, @@ -53,6 +62,12 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw | preventEditingUnlessCtrlPressed | T3Ui.EditingFlags.PreventZoomWithMouseWheel); + var showPopupIcon = innerRect.GetHeight()> ImGui.GetFrameHeight()* T3Ui.UiScaleFactor * 2; + if (showPopupIcon && CurveEditPopup.DrawPopupIndicator(sampleCurve.Curve.Input, ref curve, keepPositionForIcon, cloneIfModified, out var popupResult)) + { + modified2 = popupResult; + } + if ((modified2 & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing) { if (cloneIfModified) diff --git a/Editor/Gui/ChildUi/SequenceAnimUi.cs b/Editor/Gui/ChildUi/SequenceAnimUi.cs index b3bfcff1da..18d5bfc7ea 100644 --- a/Editor/Gui/ChildUi/SequenceAnimUi.cs +++ b/Editor/Gui/ChildUi/SequenceAnimUi.cs @@ -4,6 +4,7 @@ using T3.Core.Utils; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_94a392e6_3e03_4ccf_a114_e6fafa263b4f; namespace T3.Editor.Gui.ChildUi @@ -114,7 +115,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw drawList.PopClipRect(); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } // private static float _dragStartBias; diff --git a/Editor/Gui/ChildUi/SetFloatVarUi.cs b/Editor/Gui/ChildUi/SetFloatVarUi.cs index d60598ad5d..9252e4496d 100644 --- a/Editor/Gui/ChildUi/SetFloatVarUi.cs +++ b/Editor/Gui/ChildUi/SetFloatVarUi.cs @@ -3,6 +3,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_2a0c932a_eb81_4a7d_aeac_836a23b0b789; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/TriggerAnimUi.cs b/Editor/Gui/ChildUi/TriggerAnimUi.cs index 487a112d3a..602b5382b1 100644 --- a/Editor/Gui/ChildUi/TriggerAnimUi.cs +++ b/Editor/Gui/ChildUi/TriggerAnimUi.cs @@ -6,6 +6,7 @@ using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_95d586a2_ee14_4ff5_a5bb_40c497efde95; namespace T3.Editor.Gui.ChildUi @@ -131,7 +132,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw } drawList.PopClipRect(); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } private static float _dragStartBias; diff --git a/Editor/Gui/ChildUi/TriggerUi.cs b/Editor/Gui/ChildUi/TriggerUi.cs index 93ef64cc20..8970c08a70 100644 --- a/Editor/Gui/ChildUi/TriggerUi.cs +++ b/Editor/Gui/ChildUi/TriggerUi.cs @@ -1,8 +1,13 @@ -using System.Linq; +using System; +using System.Linq; using System.Numerics; using ImGuiNET; using T3.Core.Operator; +using T3.Editor.Gui.ChildUi.WidgetUi; +using T3.Editor.Gui.Graph; +using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_0bec016a_5e1b_467a_8273_368d4d6b9935; namespace T3.Editor.Gui.ChildUi @@ -17,36 +22,65 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw return SymbolChildUi.CustomUiResult.None; } - ImGui.PushID(instance.SymbolChildId.GetHashCode()); + var dragWidth = WidgetElements.DrawDragIndicator(screenRect, drawList); + var colorAsVec4 = trigger.ColorInGraph.TypedInputValue.Value; + var color = new Color(colorAsVec4); + + var activeRect = screenRect; + activeRect.Min.X += dragWidth; + ImGui.PushID(instance.SymbolChildId.GetHashCode()); screenRect.Expand(-4); - - ImGui.SetCursorScreenPos(screenRect.Min + new Vector2(2, 2)); + ImGui.SetCursorScreenPos(screenRect.Min); var symbolChild = instance.Parent.Symbol.Children.Single(c => c.Id == instance.SymbolChildId); ImGui.PushClipRect(screenRect.Min, screenRect.Max, true); + var refValue = trigger.BoolValue.Value; var label = string.IsNullOrEmpty(symbolChild.Name) ? "Trigger" : symbolChild.ReadableName; - ImGui.Button(label, screenRect.GetSize()); - if (ImGui.IsItemActivated()) - { - trigger.BoolValue.TypedInputValue.Value = true; - trigger.BoolValue.Input.IsDefault = false; - trigger.BoolValue.DirtyFlag.Invalidate(); + drawList.AddRectFilled(activeRect.Min, activeRect.Max, color.Fade(refValue ? 0.5f : 0.1f)); + var canvasScale = GraphCanvas.Current.Scale.Y; - } - else if (ImGui.IsItemDeactivated()) + var font = WidgetElements.GetPrimaryLabelFont(canvasScale); + var labelColor = WidgetElements.GetPrimaryLabelColor(canvasScale); + + ImGui.PushFont(font); + var labelSize = ImGui.CalcTextSize(label); + + var labelPos = activeRect.GetCenter() - labelSize/2 - new Vector2(3 * canvasScale,0); + drawList.AddText(font, font.FontSize, labelPos, labelColor, label); + ImGui.PopFont(); + + if (!trigger.BoolValue.IsConnected) { - trigger.BoolValue.TypedInputValue.Value = false; - trigger.BoolValue.Input.IsDefault = false; - trigger.BoolValue.DirtyFlag.Invalidate(); + var isHoveredOrActive = trigger.SymbolChildId == activeInputId || + ImGui.IsWindowHovered() && activeRect.Contains(ImGui.GetMousePos()); + if (isHoveredOrActive) + { + if (ImGui.IsMouseClicked(ImGuiMouseButton.Left)) + { + trigger.BoolValue.SetTypedInputValue(true); + activeInputId = trigger.SymbolChildId; + } + else if (ImGui.IsMouseReleased(ImGuiMouseButton.Left)) + { + activeInputId = Guid.Empty; + trigger.BoolValue.SetTypedInputValue(false); + } + } } ImGui.PopClipRect(); ImGui.PopID(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventTooltip + | SymbolChildUi.CustomUiResult.PreventOpenParameterPopUp + | SymbolChildUi.CustomUiResult.PreventInputLabels; } + + private static Guid activeInputId; } } \ No newline at end of file diff --git a/Editor/Gui/ChildUi/ValueUi.cs b/Editor/Gui/ChildUi/ValueUi.cs index 03f4e3cdbc..9af289786c 100644 --- a/Editor/Gui/ChildUi/ValueUi.cs +++ b/Editor/Gui/ChildUi/ValueUi.cs @@ -9,6 +9,7 @@ using T3.Editor.Gui.Interaction; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_5d7d61ae_0a41_4ffa_a51d_93bab665e7fe; namespace T3.Editor.Gui.ChildUi @@ -20,6 +21,12 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw if (!(instance is Value valueInstance)) return SymbolChildUi.CustomUiResult.None; + var dragWidth = WidgetElements.DrawDragIndicator(area, drawList); + var usableArea = area; + area.Min.X += dragWidth; + + drawList.AddRectFilled(area.Min, area.Max, UiColors.BackgroundFull.Fade(0.1f)); + var symbolChild = valueInstance.Parent.Symbol.Children.Single(c => c.Id == valueInstance.SymbolChildId); drawList.PushClipRect(area.Min, area.Max, true); @@ -70,16 +77,11 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw if (_activeJogDialInputSlot == inputSlot) { + var restarted = ImGui.IsItemActivated(); if (ImGui.IsItemActive()) { - var modified = JogDialOverlay.Draw(ref value, ImGui.IsItemActivated(), _jogDialCenter, double.NegativeInfinity, double.PositiveInfinity, - 0.01f); - if (modified) - { - inputSlot.TypedInputValue.Value = (float)value; - inputSlot.Input.IsDefault = false; - inputSlot.DirtyFlag.Invalidate(); - } + SingleValueEdit.DrawValueEditGizmo(ref value, restarted, _jogDialCenter,double.NegativeInfinity, double.PositiveInfinity, false, 0.025f); + inputSlot.SetTypedInputValue((float)value); } else { @@ -101,7 +103,10 @@ public static SymbolChildUi.CustomUiResult DrawChildUi(Instance instance, ImDraw } drawList.PopClipRect(); - return SymbolChildUi.CustomUiResult.Rendered | SymbolChildUi.CustomUiResult.PreventInputLabels | SymbolChildUi.CustomUiResult.PreventOpenSubGraph; + return SymbolChildUi.CustomUiResult.Rendered + | SymbolChildUi.CustomUiResult.PreventOpenSubGraph + | SymbolChildUi.CustomUiResult.PreventInputLabels + | SymbolChildUi.CustomUiResult.PreventTooltip; } private static Vector2 _jogDialCenter; diff --git a/Editor/Gui/ChildUi/WidgetUi/MicroGraph.cs b/Editor/Gui/ChildUi/WidgetUi/MicroGraph.cs index 113d1c520d..abc604ed46 100644 --- a/Editor/Gui/ChildUi/WidgetUi/MicroGraph.cs +++ b/Editor/Gui/ChildUi/WidgetUi/MicroGraph.cs @@ -119,7 +119,7 @@ public static bool Draw(ref float offset, ref float smoothing, float fragment, I drawList.AddPolyline(ref GraphLinePoints[0], 4, curveLineColor, ImDrawFlags.None, 1); // Draw offset label - if (h > 14) + if (!string.IsNullOrEmpty(valueText) && h > 14) { ImGui.PushFont(Fonts.FontSmall); diff --git a/Editor/Gui/ChildUi/WidgetUi/SpeedRate.cs b/Editor/Gui/ChildUi/WidgetUi/SpeedRate.cs index 33010875c7..c08ff5a0d8 100644 --- a/Editor/Gui/ChildUi/WidgetUi/SpeedRate.cs +++ b/Editor/Gui/ChildUi/WidgetUi/SpeedRate.cs @@ -20,11 +20,11 @@ private SpeedRate(float f, string label) new (0.125f, "1/8"), new (0.25f, "1/4"), new (0.5f, "1/2"), - new (1, "1"), - new (4, "x4"), - new (8, "x8"), - new (16, "x16"), - new (32, "x32"), + new (1, "1×"), + new (4, "4×"), + new (8, "8×"), + new (16, "16×"), + new (32, "32×"), }; public static int FindClosestRateIndex(float rate) diff --git a/Editor/Gui/ChildUi/WidgetUi/ValueLabel.cs b/Editor/Gui/ChildUi/WidgetUi/ValueLabel.cs index 71f1dd78fa..9614940ed5 100644 --- a/Editor/Gui/ChildUi/WidgetUi/ValueLabel.cs +++ b/Editor/Gui/ChildUi/WidgetUi/ValueLabel.cs @@ -35,11 +35,12 @@ public static bool Draw(ImDrawListPtr drawList, ImRect screenRect, Vector2 align ImGui.InvisibleButton("button", labelSize); double value2 = inputSlot.TypedInputValue.Value; + var restarted = false; if (ImGui.IsItemActivated() && ImGui.GetIO().KeyCtrl) { _jogDailCenter = ImGui.GetIO().MousePos; _jogDialValue = inputSlot; - drawList.AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), UiColors.WidgetHighlight); + restarted = true; } if (ImGui.IsItemActive() || !ImGui.IsAnyItemActive()) @@ -55,14 +56,9 @@ public static bool Draw(ImDrawListPtr drawList, ImRect screenRect, Vector2 align { if (ImGui.IsItemActive()) { - modified = JogDialOverlay.Draw(ref value, ImGui.IsItemActivated(), _jogDailCenter, double.NegativeInfinity, double.PositiveInfinity, - 0.01f); - if (modified) - { - inputSlot.TypedInputValue.Value = (float)value; - inputSlot.Input.IsDefault = false; - inputSlot.DirtyFlag.Invalidate(); - } + SingleValueEdit.DrawValueEditGizmo(ref value, restarted, _jogDailCenter,double.NegativeInfinity, double.PositiveInfinity, false, 0.025f); + inputSlot.SetTypedInputValue((float)value); + modified = true; } else { @@ -73,7 +69,7 @@ public static bool Draw(ImDrawListPtr drawList, ImRect screenRect, Vector2 align } // Draw aligned label - { + if(!string.IsNullOrEmpty(valueText)){ ImGui.PushFont(Fonts.FontSmall); var labelSize = ImGui.CalcTextSize(valueText); var space = screenRect.GetSize() - labelSize; diff --git a/Editor/Gui/ChildUi/WidgetUi/WidgetElements.cs b/Editor/Gui/ChildUi/WidgetUi/WidgetElements.cs index 6a28b19ab7..a5ac3c10a2 100644 --- a/Editor/Gui/ChildUi/WidgetUi/WidgetElements.cs +++ b/Editor/Gui/ChildUi/WidgetUi/WidgetElements.cs @@ -1,5 +1,6 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; using ImGuiNET; using T3.Core.Operator.Slots; using T3.Core.Utils; @@ -16,31 +17,37 @@ public static class WidgetElements { public static void DrawPrimaryTitle(ImDrawListPtr drawList, ImRect widgetRect, string formattedValue) { + if (string.IsNullOrEmpty(formattedValue)) + return; + var canvasScale = GraphCanvas.Current.Scale.Y; var font = canvasScale < ScaleFactors.NormalScale ? Fonts.FontSmall : canvasScale > ScaleFactors.BigScale ? Fonts.FontLarge : Fonts.FontNormal; - + ImGui.PushFont(font); var fadingColor = UiColors.WidgetTitle - .Fade(MathUtils.NormalizeAndClamp - ( - canvasScale, - ScaleFactors.SmallerScale, - ScaleFactors.SmallScale)); - + .Fade(MathUtils.NormalizeAndClamp + ( + canvasScale, + ScaleFactors.SmallerScale, + ScaleFactors.SmallScale)); + //var labelSize = ImGui.CalcTextSize(formattedValue); drawList.AddText(new Vector2 (widgetRect.Min.X + 5, widgetRect.Min.Y + 2), fadingColor, formattedValue); ImGui.PopFont(); - } - + } + public static void DrawSmallTitle(ImDrawListPtr drawList, ImRect widgetRect, string title) { + if (string.IsNullOrEmpty(title)) + return; + var canvasScale = GraphCanvas.Current.Scale.Y / T3Ui.UiScaleFactor; var font = canvasScale > ScaleFactors.LargerScale ? Fonts.FontNormal @@ -49,85 +56,102 @@ public static void DrawSmallTitle(ImDrawListPtr drawList, ImRect widgetRect, str ImGui.PushFont(font); var fadingColor = UiColors.WidgetTitle - .Fade(MathUtils.NormalizeAndClamp - ( - canvasScale, - ScaleFactors.NormalScale, - ScaleFactors.BigScale)); + .Fade(MathUtils.NormalizeAndClamp + ( + canvasScale, + ScaleFactors.NormalScale, + ScaleFactors.BigScale)); drawList.AddText(widgetRect.Min + new Vector2(5, 2), fadingColor, title); ImGui.PopFont(); } - - public static void DrawPrimaryValue(ImDrawListPtr drawList, ImRect widgetRect, string formattedValue) + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ImFontPtr GetPrimaryLabelFont(float canvasScale) { - var canvasScale = GraphCanvas.Current.Scale.Y; var font = canvasScale < ScaleFactors.NormalScale ? Fonts.FontSmall : canvasScale > ScaleFactors.BigScale ? Fonts.FontLarge : Fonts.FontNormal; + return font; + } - ImGui.PushFont(font); - var fadingColor = UiColors.WidgetTitle - .Fade(MathUtils.NormalizeAndClamp - ( - canvasScale, - ScaleFactors.SmallerScale, - ScaleFactors.SmallScale)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Color GetPrimaryLabelColor(float canvasScale) + { + return UiColors.WidgetTitle + .Fade(MathUtils.NormalizeAndClamp + ( + canvasScale, + ScaleFactors.SmallerScale, + ScaleFactors.SmallScale)); + } + public static void DrawPrimaryValue(ImDrawListPtr drawList, ImRect widgetRect, string formattedValue) + { + if (string.IsNullOrEmpty(formattedValue)) + return; + + var canvasScale = GraphCanvas.Current.Scale.Y; + + ImGui.PushFont(GetPrimaryLabelFont(canvasScale)); var labelSize = ImGui.CalcTextSize(formattedValue); + drawList.AddText(new Vector2 (widgetRect.Min.X + 5, - widgetRect.Max.Y - labelSize.Y -2), - fadingColor, formattedValue); - + widgetRect.Max.Y - labelSize.Y - 2), + GetPrimaryLabelColor(canvasScale), + formattedValue); ImGui.PopFont(); } - + public static void DrawSmallValue(ImDrawListPtr drawList, ImRect widgetRect, string title) { + if (string.IsNullOrEmpty(title)) + return; + var canvasScale = GraphCanvas.Current.Scale.Y / T3Ui.UiScaleFactor; var font = canvasScale > ScaleFactors.LargerScale ? Fonts.FontNormal : Fonts.FontSmall; - + ImGui.PushFont(font); - + var fadingColor = UiColors.WidgetTitle - .Fade(MathUtils.NormalizeAndClamp - ( - canvasScale, - ScaleFactors.NormalScale, - ScaleFactors.BigScale)); + .Fade(MathUtils.NormalizeAndClamp + ( + canvasScale, + ScaleFactors.NormalScale, + ScaleFactors.BigScale)); var labelSize = ImGui.CalcTextSize(title); drawList.AddText(new Vector2 (widgetRect.Min.X + 5, - widgetRect.Max.Y - labelSize.Y -2), + widgetRect.Max.Y - labelSize.Y - 2), fadingColor, title); - + ImGui.PopFont(); - } - - public static bool DrawRateLabelWithTitle(InputSlot inputSlot, ImRect selectableScreenRect, ImDrawListPtr drawList, string nodeLabel) + } + + public static bool DrawRateLabelWithTitle(InputSlot inputSlot, ImRect selectableScreenRect, ImDrawListPtr drawList, string nodeLabel) { var rate = inputSlot.Input.Value is InputValue floatValue ? floatValue.Value : inputSlot.Value; var modified = false; - - var currentRateIndex = SpeedRate.FindClosestRateIndex(rate); - var formattedValue = currentRateIndex == -1 - ? $"{rate:0.0}" - : SpeedRate.RelevantRates[currentRateIndex].Label; + + var currentRateIndex = SpeedRate.FindClosestRateIndex(rate); + var formattedValue = currentRateIndex == -1 + ? $"{rate:0.0}×" + : SpeedRate.RelevantRates[currentRateIndex].Label; DrawPrimaryValue(drawList, selectableScreenRect, formattedValue); - + var isActive = false; var editUnlocked = ImGui.GetIO().KeyCtrl; - + // Speed Interaction var speedRect = selectableScreenRect; - speedRect.Max.X = speedRect.Min.X + speedRect.GetWidth() * 0.2f; + speedRect.Max.X = speedRect.Min.X + speedRect.GetWidth() * 0.2f; ImGui.SetCursorScreenPos(speedRect.Min); if (editUnlocked) @@ -140,7 +164,7 @@ public static bool DrawRateLabelWithTitle(InputSlot inputSlot, ImRect sel isActive = ImGui.IsItemActive(); } - + if (isActive && ImGui.IsMouseDragging(ImGuiMouseButton.Left)) { var dragDelta = ImGui.GetMouseDragDelta(ImGuiMouseButton.Left, 1); @@ -160,11 +184,63 @@ public static bool DrawRateLabelWithTitle(InputSlot inputSlot, ImRect sel ImGui.ResetMouseDragDelta(); } } - + DrawSmallTitle(drawList, selectableScreenRect, nodeLabel); - + return modified; - } + } + + /// + /// Draws a drag indicator on the left side of a graph operator and returns the computed width in pixels + /// + public static float DrawDragIndicator(ImRect visibleScreenRect, ImDrawListPtr drawList) + { + var canvasScale = GraphCanvas.Current.Scale.Y / T3Ui.UiScaleFactor; + var width = Math.Max(10 * T3Ui.UiScaleFactor, (int)(7 * canvasScale)); + + if (width < 3) + return 0; + + var drawRect = visibleScreenRect; + drawRect.Max.X = drawRect.Min.X + width; + + var center = drawRect.GetCenter(); + + const int rowCount = 4; + const int columnCount = 2; + var digitRadius = (width / 6); + + var patternSize = new Vector2( + digitRadius * (columnCount * 2 - 1), + digitRadius * (rowCount * 2 - 1)); + var patternMin = center - patternSize / 2; + var size = Vector2.One * digitRadius; + + var color = UiColors.BackgroundFull.Fade(0.2f); + if (digitRadius > 0) + { + for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) + { + for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + var p = patternMin + new Vector2( + columnIndex * digitRadius * 2, + rowIndex * digitRadius * 2); + + drawList.AddRectFilled(p, + p + size, + color); + } + } + } + + drawList.AddRectFilled(new Vector2(visibleScreenRect.Min.X + width - 1, visibleScreenRect.Min.Y), + new Vector2(visibleScreenRect.Min.X + width, visibleScreenRect.Max.Y), + color + ); + + return width; + } private static class WidgetHeights { diff --git a/Editor/Gui/ChildUi/_Jitter2dUi.cs b/Editor/Gui/ChildUi/_Jitter2dUi.cs index b19bae9675..a183e88f61 100644 --- a/Editor/Gui/ChildUi/_Jitter2dUi.cs +++ b/Editor/Gui/ChildUi/_Jitter2dUi.cs @@ -2,6 +2,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_23794a1f_372d_484b_ac31_9470d0e77819; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/ChildUi/_JitterUi.cs b/Editor/Gui/ChildUi/_JitterUi.cs index a09768e585..734a386a90 100644 --- a/Editor/Gui/ChildUi/_JitterUi.cs +++ b/Editor/Gui/ChildUi/_JitterUi.cs @@ -2,6 +2,7 @@ using T3.Core.Operator; using T3.Editor.Gui.ChildUi.WidgetUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using T3.Operators.Types.Id_3b0eb327_6ad8_424f_bca7_ccbfa2c9a986; namespace T3.Editor.Gui.ChildUi diff --git a/Editor/Gui/Commands/Annotations/AddAnnotationCommand.cs b/Editor/Gui/Commands/Annotations/AddAnnotationCommand.cs index 271e895afa..552e3dcae5 100644 --- a/Editor/Gui/Commands/Annotations/AddAnnotationCommand.cs +++ b/Editor/Gui/Commands/Annotations/AddAnnotationCommand.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using T3.Editor.Gui.Graph; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Annotations { diff --git a/Editor/Gui/Commands/Annotations/DeleteAnnotationCommand.cs b/Editor/Gui/Commands/Annotations/DeleteAnnotationCommand.cs index 66febfb6e5..68fb44919c 100644 --- a/Editor/Gui/Commands/Annotations/DeleteAnnotationCommand.cs +++ b/Editor/Gui/Commands/Annotations/DeleteAnnotationCommand.cs @@ -1,4 +1,5 @@ using T3.Editor.Gui.Graph; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Annotations { diff --git a/Editor/Gui/Commands/Graph/AddConnectionCommand.cs b/Editor/Gui/Commands/Graph/AddConnectionCommand.cs index 8a0bb6b486..88455fb2b4 100644 --- a/Editor/Gui/Commands/Graph/AddConnectionCommand.cs +++ b/Editor/Gui/Commands/Graph/AddConnectionCommand.cs @@ -1,5 +1,6 @@ using System; using T3.Core.Operator; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/AddSymbolChildCommand.cs b/Editor/Gui/Commands/Graph/AddSymbolChildCommand.cs index bc254f225b..4c9bc938d0 100644 --- a/Editor/Gui/Commands/Graph/AddSymbolChildCommand.cs +++ b/Editor/Gui/Commands/Graph/AddSymbolChildCommand.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; using T3.Core.Operator; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/ChangeInputValueCommand.cs b/Editor/Gui/Commands/Graph/ChangeInputValueCommand.cs index 74607330a9..cdcad6449e 100644 --- a/Editor/Gui/Commands/Graph/ChangeInputValueCommand.cs +++ b/Editor/Gui/Commands/Graph/ChangeInputValueCommand.cs @@ -5,6 +5,7 @@ using T3.Core.Logging; using T3.Core.Operator; using T3.Core.Operator.Slots; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/ChangeInstanceIsDisabledCommand.cs b/Editor/Gui/Commands/Graph/ChangeInstanceIsDisabledCommand.cs index 4a6dd0c066..754bc5fb8c 100644 --- a/Editor/Gui/Commands/Graph/ChangeInstanceIsDisabledCommand.cs +++ b/Editor/Gui/Commands/Graph/ChangeInstanceIsDisabledCommand.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using T3.Core.Logging; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/ChangeSymbolChildNameCommand.cs b/Editor/Gui/Commands/Graph/ChangeSymbolChildNameCommand.cs index b49c8fbb4b..cc77077ef4 100644 --- a/Editor/Gui/Commands/Graph/ChangeSymbolChildNameCommand.cs +++ b/Editor/Gui/Commands/Graph/ChangeSymbolChildNameCommand.cs @@ -1,5 +1,6 @@ using System; using T3.Core.Operator; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/CopySymbolChildrenCommand.cs b/Editor/Gui/Commands/Graph/CopySymbolChildrenCommand.cs index 154120288e..030961cb3c 100644 --- a/Editor/Gui/Commands/Graph/CopySymbolChildrenCommand.cs +++ b/Editor/Gui/Commands/Graph/CopySymbolChildrenCommand.cs @@ -5,6 +5,7 @@ using T3.Core.Logging; using T3.Core.Operator; using T3.Editor.Gui.Graph; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/DeleteSymbolChildrenCommand.cs b/Editor/Gui/Commands/Graph/DeleteSymbolChildrenCommand.cs index 67c37d8af1..67c5b6ea2d 100644 --- a/Editor/Gui/Commands/Graph/DeleteSymbolChildrenCommand.cs +++ b/Editor/Gui/Commands/Graph/DeleteSymbolChildrenCommand.cs @@ -5,6 +5,7 @@ using T3.Core.Animation; using T3.Core.Operator; using T3.Core.Operator.Slots; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Graph/ModifyCanvasElementsCommand.cs b/Editor/Gui/Commands/Graph/ModifyCanvasElementsCommand.cs index 021253d36e..0d397bc90f 100644 --- a/Editor/Gui/Commands/Graph/ModifyCanvasElementsCommand.cs +++ b/Editor/Gui/Commands/Graph/ModifyCanvasElementsCommand.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Numerics; using T3.Editor.Gui.Selection; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Graph { diff --git a/Editor/Gui/Commands/Variations/AddPresetOrVariationCommand.cs b/Editor/Gui/Commands/Variations/AddPresetOrVariationCommand.cs index 27e089295c..2ace64064a 100644 --- a/Editor/Gui/Commands/Variations/AddPresetOrVariationCommand.cs +++ b/Editor/Gui/Commands/Variations/AddPresetOrVariationCommand.cs @@ -4,6 +4,7 @@ using T3.Core.Operator; using T3.Editor.Gui.Interaction.Variations; using T3.Editor.Gui.Interaction.Variations.Model; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Commands.Variations { diff --git a/Editor/Gui/Dialog/MigrateOperatorsDialog.cs b/Editor/Gui/Dialog/MigrateOperatorsDialog.cs index 869344c4e3..d08bead470 100644 --- a/Editor/Gui/Dialog/MigrateOperatorsDialog.cs +++ b/Editor/Gui/Dialog/MigrateOperatorsDialog.cs @@ -22,7 +22,7 @@ public MigrateOperatorsDialog() public void Draw() { - FormInputs.ResetIndent(); + FormInputs.SetIndentToParameters(); if (BeginDialog("Import Operators from another Tooll installation")) { ImGui.BeginChild("options", new Vector2(ImGui.GetContentRegionAvail().X - 400, -1)); @@ -190,8 +190,20 @@ private void ScanFolder() private void MigrateSelection() { - var allRemoteT3Files = Directory.GetFiles(_otherOperatorNamespaceDirectory, "*.t3", SearchOption.AllDirectories); - var allRemoteT3UiFiles = Directory.GetFiles(_otherOperatorNamespaceDirectory, "*.t3ui", SearchOption.AllDirectories); + string[] allRemoteT3Files; + string[] allRemoteT3UiFiles; + + try + { + allRemoteT3Files = Directory.GetFiles(_otherOperatorNamespaceDirectory, "*.t3", SearchOption.AllDirectories); + allRemoteT3UiFiles = Directory.GetFiles(_otherOperatorNamespaceDirectory, "*.t3ui", SearchOption.AllDirectories); + } + catch (Exception e) + { + Log.Error("Migration failed: " + e.Message); + return; + } + foreach (var item in _scanResults) { diff --git a/Editor/Gui/Dialog/SearchDialog.cs b/Editor/Gui/Dialog/SearchDialog.cs index acdfee7c6c..3eba935311 100644 --- a/Editor/Gui/Dialog/SearchDialog.cs +++ b/Editor/Gui/Dialog/SearchDialog.cs @@ -46,7 +46,7 @@ public void Draw() } var needsUpdate = _justOpened; - FormInputs.SetIndent(0); + FormInputs.SetIndentToLeft(); FormInputs.SetWidth(0.7f); needsUpdate |= FormInputs.AddStringInput("", ref _searchString, "Search", null, null, string.Empty); diff --git a/Editor/Gui/Graph/AnnotationElement.cs b/Editor/Gui/Graph/AnnotationElement.cs index 413389aaca..0fe8a0d736 100644 --- a/Editor/Gui/Graph/AnnotationElement.cs +++ b/Editor/Gui/Graph/AnnotationElement.cs @@ -5,6 +5,7 @@ using ImGuiNET; using T3.Core.IO; using T3.Core.Operator; +using T3.Core.Utils; using T3.Editor.Gui.Commands; using T3.Editor.Gui.Commands.Annotations; using T3.Editor.Gui.Commands.Graph; @@ -12,6 +13,7 @@ using T3.Editor.Gui.Selection; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph { @@ -49,7 +51,7 @@ internal static void Draw(Annotation annotation) // Resize indicator { ImGui.SetMouseCursor(ImGuiMouseCursor.ResizeNWSE); - ImGui.SetCursorScreenPos(_screenArea.Max - new Vector2(10, 10)); + ImGui.SetCursorScreenPos(_screenArea.Max - new Vector2(10, 10) * T3Ui.UiScaleFactor); ImGui.Button("##resize", new Vector2(10, 10) * T3Ui.UiScaleFactor); if (ImGui.IsItemActive() && ImGui.IsMouseDragging(ImGuiMouseButton.Left)) { @@ -61,10 +63,10 @@ internal static void Draw(Annotation annotation) } // Background - const float backgroundAlpha = 0.1f; - const float headerHoverAlpha = 0.2f; + const float backgroundAlpha = 0.2f; + const float headerHoverAlpha = 0.3f; - drawList.AddRectFilled(_screenArea.Min, _screenArea.Max, annotation.Color.Fade(backgroundAlpha)); + drawList.AddRectFilled(_screenArea.Min, _screenArea.Max, UiColors.BackgroundFull.Fade(backgroundAlpha)); // Interaction ImGui.SetCursorScreenPos(clickableArea.Min); @@ -91,7 +93,7 @@ internal static void Draw(Annotation annotation) var borderColor = annotation.IsSelected ? UiColors.Selection - : annotation.Color.Fade(isHeaderHovered ? headerHoverAlpha : backgroundAlpha); + : UiColors.BackgroundFull.Fade(isHeaderHovered ? headerHoverAlpha : backgroundAlpha); const float thickness = 1; drawList.AddRect(_screenArea.Min - Vector2.One * thickness, @@ -102,17 +104,23 @@ internal static void Draw(Annotation annotation) thickness); // Label - { - var isScaledDown = GraphCanvas.Current.Scale.X < 1 * T3Ui.UiScaleFactor; - ImGui.PushFont(isScaledDown ? Fonts.FontSmall : Fonts.FontNormal); - + if(!string.IsNullOrEmpty(annotation.Title)) { + var canvasScale = GraphCanvas.Current.Scale.X; + var font = annotation.Title.StartsWith("# ") ? Fonts.FontLarge: Fonts.FontNormal; + var fade = MathUtils.SmootherStep(0.25f, 0.6f, canvasScale); drawList.PushClipRect(_screenArea.Min, _screenArea.Max, true); - var labelPos = _screenArea.Min + new Vector2(4, 4); - - drawList.AddText(labelPos, - ColorVariations.OperatorLabel.Apply(annotation.Color), + var labelPos = _screenArea.Min + new Vector2(8, 6) * T3Ui.DisplayScaleFactor; + + var fontSize = canvasScale > 1 + ? font.FontSize + : canvasScale > Fonts.FontSmall.Scale / Fonts.FontNormal.Scale + ? font.FontSize + : font.FontSize * canvasScale; + drawList.AddText(font, + fontSize, + labelPos, + ColorVariations.OperatorLabel.Apply(annotation.Color.Fade(fade)), annotation.Title); - ImGui.PopFont(); drawList.PopClipRect(); } diff --git a/Editor/Gui/Graph/Dialogs/AddInputDialog.cs b/Editor/Gui/Graph/Dialogs/AddInputDialog.cs index b033e91390..6a6d9be353 100644 --- a/Editor/Gui/Graph/Dialogs/AddInputDialog.cs +++ b/Editor/Gui/Graph/Dialogs/AddInputDialog.cs @@ -23,15 +23,27 @@ public void Draw(Symbol symbol) { if (BeginDialog("Add parameter input")) { + var warning = string.Empty; + var isValid = GraphUtils.IsNewSymbolNameValid(_parameterName) && _selectedType != null; + + if (!isValid) + { + warning = "parameter must not contain spaces or non-special characters."; + } + else if(symbol.InputDefinitions.Exists(i => i.Name == _parameterName)) + { + warning = "Parameter name already exists."; + } + FormInputs.SetIndent(100); - FormInputs.AddStringInput("Name", ref _parameterName); + FormInputs.AddStringInput("Name", ref _parameterName, "ParameterName", warning); FormInputs.DrawInputLabel("Type"); TypeSelector.Draw(ref _selectedType); FormInputs.AddCheckBox("Multi-Input", ref _multiInput); - var isValid = GraphUtils.IsNewSymbolNameValid(_parameterName) && _selectedType != null; + FormInputs.ApplyIndent(); if (CustomComponents.DisablableButton("Add", isValid)) { diff --git a/Editor/Gui/Graph/Dialogs/CombineToSymbolDialog.cs b/Editor/Gui/Graph/Dialogs/CombineToSymbolDialog.cs index d80b1c3656..b7ef85c4e2 100644 --- a/Editor/Gui/Graph/Dialogs/CombineToSymbolDialog.cs +++ b/Editor/Gui/Graph/Dialogs/CombineToSymbolDialog.cs @@ -8,6 +8,7 @@ using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Dialogs { diff --git a/Editor/Gui/Graph/Dialogs/DuplicateSymbolDialog.cs b/Editor/Gui/Graph/Dialogs/DuplicateSymbolDialog.cs index b7e8c3c77b..74cdd5887d 100644 --- a/Editor/Gui/Graph/Dialogs/DuplicateSymbolDialog.cs +++ b/Editor/Gui/Graph/Dialogs/DuplicateSymbolDialog.cs @@ -8,6 +8,7 @@ using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Dialogs { @@ -15,7 +16,7 @@ public class DuplicateSymbolDialog : ModalDialog { public void Draw(Instance compositionOp, List selectedChildUis, ref string nameSpace, ref string newTypeName, ref string description) { - DialogSize = new Vector2(500, 280); + DialogSize = new Vector2(500, 300); if (BeginDialog("Duplicate as new symbol")) { diff --git a/Editor/Gui/Graph/Dialogs/EditCommentDialog.cs b/Editor/Gui/Graph/Dialogs/EditCommentDialog.cs new file mode 100644 index 0000000000..f914a13401 --- /dev/null +++ b/Editor/Gui/Graph/Dialogs/EditCommentDialog.cs @@ -0,0 +1,62 @@ +using System.Linq; +using System.Numerics; +using ImGuiNET; +using T3.Editor.Gui.Graph.Interaction; +using T3.Editor.Gui.Styling; +using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; + +namespace T3.Editor.Gui.Graph.Dialogs +{ + public class EditCommentDialog : ModalDialog + { + public void Draw() + { + DialogSize = new Vector2(500, 450); + + if (BeginDialog("Edit comment")) + { + var instance = NodeSelection.GetSelectedInstance(); + + if (instance?.Parent == null) + { + CustomComponents.EmptyWindowMessage("Please select operator\nto add comment"); + } + else + { + var parentSymbolId = instance.Parent.Symbol.Id; + var symbolUi = SymbolUiRegistry.Entries[parentSymbolId]; + var symbolChildUi = symbolUi.ChildUis.FirstOrDefault(c => c.Id == instance.SymbolChildId); + if (symbolChildUi == null) + { + CustomComponents.EmptyWindowMessage("Sorry, can't find UI definition for operator."); + } + else + { + var comment = symbolChildUi.Comment ?? string.Empty; + + ImGui.PushFont(Fonts.FontLarge); + ImGui.Text(symbolChildUi.SymbolChild.Symbol.Name); + ImGui.PopFont(); + + if (ImGui.IsWindowAppearing()) + ImGui.SetKeyboardFocusHere(); + + if (ImGui.InputTextMultiline("##comment", ref comment, 2000, new Vector2(-1, 300), ImGuiInputTextFlags.None)) + { + symbolChildUi.Comment = comment; + symbolUi.FlagAsModified(); + } + } + } + if (ImGui.Button("Close")) + { + ImGui.CloseCurrentPopup(); + } + + EndDialogContent(); + } + EndDialog(); + } + } +} \ No newline at end of file diff --git a/Editor/Gui/Graph/Dialogs/EditNodeOutputDialog.cs b/Editor/Gui/Graph/Dialogs/EditNodeOutputDialog.cs index eecdf20d66..a76666253a 100644 --- a/Editor/Gui/Graph/Dialogs/EditNodeOutputDialog.cs +++ b/Editor/Gui/Graph/Dialogs/EditNodeOutputDialog.cs @@ -4,6 +4,7 @@ using T3.Core.Operator; using T3.Core.Operator.Slots; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Dialogs { diff --git a/Editor/Gui/Graph/Dialogs/EditSymbolDescriptionDialog.cs b/Editor/Gui/Graph/Dialogs/EditSymbolDescriptionDialog.cs index 078f1ecec5..6c1a48e2fe 100644 --- a/Editor/Gui/Graph/Dialogs/EditSymbolDescriptionDialog.cs +++ b/Editor/Gui/Graph/Dialogs/EditSymbolDescriptionDialog.cs @@ -3,6 +3,7 @@ using T3.Core.Operator; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Dialogs { @@ -11,29 +12,69 @@ public class EditSymbolDescriptionDialog : ModalDialog public void Draw(Symbol operatorSymbol) { DialogSize = new Vector2(1100, 700); - + if (BeginDialog("Edit description")) { var symbolUi = SymbolUiRegistry.Entries[operatorSymbol.Id]; var desc = symbolUi.Description ?? string.Empty; - + ImGui.PushFont(Fonts.FontLarge); ImGui.Text(symbolUi.Symbol.Name); ImGui.PopFont(); - + if (ImGui.IsWindowAppearing()) ImGui.SetKeyboardFocusHere(); - ImGui.InputTextMultiline("##name", ref desc, 2000, new Vector2(-1,400), ImGuiInputTextFlags.None); + ImGui.InputTextMultiline("##name", ref desc, 2000, new Vector2(-1, 400), ImGuiInputTextFlags.None); symbolUi.Description = desc; + + ImGui.Text("Links..."); + var modified = false; + foreach (var l in symbolUi.Links.Values) + { + ImGui.PushID(l.Id.GetHashCode()); + + ImGui.SetNextItemWidth(150); + modified |= FormInputs.DrawEnumDropdown(ref l.Type, "type"); + + ImGui.SameLine(); + modified |= CustomComponents.DrawInputFieldWithPlaceholder("URL", ref l.Url, 220); + + ImGui.SameLine(); + modified |= CustomComponents.DrawInputFieldWithPlaceholder("Title", ref l.Title, 220); + + + ImGui.SameLine(); + modified |= CustomComponents.DrawInputFieldWithPlaceholder("Description", ref l.Description); + + ImGui.SameLine(); + if (CustomComponents.IconButton(Icon.Trash, Vector2.One * ImGui.GetFrameHeight())) + { + symbolUi.Links.Remove(l.Id); + ImGui.PopID(); + break; // prevent further iteration on dict + } + ImGui.PopID(); + } + + if (ImGui.Button("Add link")) + { + var newLink = new ExternalLink() { Type = ExternalLink.LinkTypes.TutorialVideo}; + symbolUi.Links.Add(newLink.Id, newLink); + modified = true; + } + if(modified) + symbolUi.FlagAsModified(); + if (ImGui.Button("Close")) { ImGui.CloseCurrentPopup(); } - + EndDialogContent(); } + EndDialog(); } } diff --git a/Editor/Gui/Graph/Dialogs/LibWarningDialog.cs b/Editor/Gui/Graph/Dialogs/LibWarningDialog.cs index 49307a57e2..7d09c4a352 100644 --- a/Editor/Gui/Graph/Dialogs/LibWarningDialog.cs +++ b/Editor/Gui/Graph/Dialogs/LibWarningDialog.cs @@ -1,4 +1,6 @@ using ImGuiNET; +using T3.Core.Operator; +using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; namespace T3.Editor.Gui.Graph.Dialogs @@ -9,27 +11,47 @@ public void Draw() { if (BeginDialog("Careful now")) { - ImGui.TextUnformatted($"You tried to open a library symbol.\nAny change would affect {DependencyCount} operators using it."); + ImGui.TextUnformatted("You tried to open a library symbol.\n" + + $"Any change would affect {DependencyCount} operators using it."); ImGui.Spacing(); if (ImGui.Button("Cancel")) { ImGui.CloseCurrentPopup(); + // the UserSettings modification get rolled-back when the user hits cancel: + // we can safely assume it was true before (since the pop-up was displayed) + UserSettings.Config.WarnBeforeLibEdit = true; } ImGui.SameLine(); if (ImGui.Button("I know what I'm doing")) { - UserSettings.Config.WarnBeforeLibEdit = false; + GraphCanvas.Current.SetCompositionToChildInstance(HandledInstance); ImGui.CloseCurrentPopup(); + } + // no sane way to "mirror" a ref, note: this whole section could be replaced + // by a simple UserSettings reference, and changing label to "Remind me next time" + // "Dont ask again" is actually the better/safer mainly bc it's the label we're all used to. + if(ImGui.TreeNode("More...")) + { + var DontWarnAgain = !UserSettings.Config.WarnBeforeLibEdit; + FormInputs.SetIndent(10); + if(FormInputs.AddCheckBox("Don't ask me again!", ref DontWarnAgain)) + { + DontWarnAgain = !DontWarnAgain; + UserSettings.Config.WarnBeforeLibEdit = !UserSettings.Config.WarnBeforeLibEdit; + } + } EndDialogContent(); + ImGui.TreePop(); } EndDialog(); } public static int DependencyCount=0; + public static Instance HandledInstance; } } \ No newline at end of file diff --git a/Editor/Gui/Graph/Dialogs/RenameSymbolDialog.cs b/Editor/Gui/Graph/Dialogs/RenameSymbolDialog.cs index 5d8d1f57d0..efbeb520d4 100644 --- a/Editor/Gui/Graph/Dialogs/RenameSymbolDialog.cs +++ b/Editor/Gui/Graph/Dialogs/RenameSymbolDialog.cs @@ -5,6 +5,7 @@ using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Dialogs { diff --git a/Editor/Gui/Graph/Graph.cs b/Editor/Gui/Graph/Graph.cs index 37086c02de..a5b09213c5 100644 --- a/Editor/Gui/Graph/Graph.cs +++ b/Editor/Gui/Graph/Graph.cs @@ -11,6 +11,7 @@ using T3.Editor.Gui.OutputUi; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using Truncon.Collections; // ReSharper disable LoopCanBeConvertedToQuery diff --git a/Editor/Gui/Graph/GraphCanvas.cs b/Editor/Gui/Graph/GraphCanvas.cs index 621c80114f..22f0ea2ffe 100644 --- a/Editor/Gui/Graph/GraphCanvas.cs +++ b/Editor/Gui/Graph/GraphCanvas.cs @@ -30,6 +30,7 @@ using T3.Editor.Gui.Windows.Output; using T3.Editor.Gui.Windows.TimeLine; using T3.Editor.SystemUi; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph { @@ -350,6 +351,11 @@ public void Draw(ImDrawListPtr dl, GraphDrawingFlags drawingFlags, float graphOp NodeNavigation.SelectBelow(); } + if (KeyboardBinding.Triggered(UserActions.AddComment)) + { + EditCommentDialog.ShowNextFrame(); + } + if (KeyboardBinding.Triggered(UserActions.SelectToLeft)) { NodeNavigation.SelectLeft(); @@ -469,6 +475,7 @@ public void Draw(ImDrawListPtr dl, GraphDrawingFlags drawingFlags, float graphOp ref _symbolNameForDialogEdits, ref _symbolDescriptionForDialog); _renameSymbolDialog.Draw(GetSelectedChildUis(), ref _symbolNameForDialogEdits); + EditCommentDialog.Draw(); _addInputDialog.Draw(CompositionOp.Symbol); _addOutputDialog.Draw(CompositionOp.Symbol); LibWarningDialog.Draw(); @@ -715,6 +722,14 @@ private void DrawContextMenuContent() { RenameInstanceOverlay.OpenForSymbolChildUi(selectedChildUis[0]); } + + if (ImGui.MenuItem("Add Comment", + KeyboardBinding.ListKeyboardShortcuts(UserActions.AddComment, false), + selected: false, + enabled: oneOpSelected)) + { + EditCommentDialog.ShowNextFrame(); + } if (ImGui.MenuItem("Arrange sub graph", KeyboardBinding.ListKeyboardShortcuts(UserActions.LayoutSelection, false), @@ -828,6 +843,17 @@ private void DrawContextMenuContent() } ImGui.Separator(); + + if (ImGui.MenuItem("Change Symbol", someOpsSelected)) + { + var startingSearchString = selectedChildUis[0].SymbolChild.Symbol.Name; + var position = selectedChildUis.Count == 1 ? selectedChildUis[0].PosOnCanvas : InverseTransformPositionFloat(ImGui.GetMousePos()); + SymbolBrowser.OpenAt(position, null, null, false, startingSearchString, symbol => + { + ChangeSymbol.ChangeOperatorSymbol(CompositionOp, selectedChildUis, symbol); + }); + } + if (ImGui.BeginMenu("Symbol definition...")) { if (ImGui.MenuItem("Rename Symbol", oneOpSelected)) @@ -1174,6 +1200,7 @@ public IEnumerable SelectableChildren private readonly DuplicateSymbolDialog _duplicateSymbolDialog = new(); private readonly RenameSymbolDialog _renameSymbolDialog = new(); public readonly EditNodeOutputDialog EditNodeOutputDialog = new(); + public static readonly EditCommentDialog EditCommentDialog = new(); public static readonly LibWarningDialog LibWarningDialog = new(); private List ChildUis { get; set; } diff --git a/Editor/Gui/Graph/GraphImageBackground.cs b/Editor/Gui/Graph/GraphImageBackground.cs index 5bb9375357..3cb5d52be9 100644 --- a/Editor/Gui/Graph/GraphImageBackground.cs +++ b/Editor/Gui/Graph/GraphImageBackground.cs @@ -13,6 +13,7 @@ using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.Windows; using T3.Editor.Gui.Windows.Output; +using T3.Editor.UiModel; using Vector2 = System.Numerics.Vector2; namespace T3.Editor.Gui.Graph @@ -73,7 +74,7 @@ public void Draw(float imageOpacity) return; _imageCanvas.SetAsCurrent(); - _evaluationContext.ShowGizmos = ShowGizmos; + _evaluationContext.ShowGizmos = _showGizmos; _evaluationContext.RequestedResolution = _selectedResolution.ComputeResolution(); _evaluationContext.SetDefaultCamera(); if (_camSelectionHandling.CameraForRendering != null) @@ -81,7 +82,11 @@ public void Draw(float imageOpacity) _evaluationContext.SetViewFromCamera(_camSelectionHandling.CameraForRendering); } + var hackToHideResolution = UserSettings.Config.ShowToolbar; + UserSettings.Config.ShowToolbar = false; viewOutputUi.DrawValue(viewOutput, _evaluationContext, recompute: true); + UserSettings.Config.ShowToolbar = hackToHideResolution; + _imageCanvas.Deactivate(); if (imageOpacity < 1) @@ -107,10 +112,10 @@ public void DrawToolbarItems() DrawResolutionSelector(); ImGui.SameLine(); - var showGizmos = ShowGizmos != T3.Core.Operator.GizmoVisibility.Off; - if (CustomComponents.ToggleIconButton(Icon.Grid, "##gizmos", ref showGizmos, Vector2.One * ImGui.GetFrameHeight())) + var showGizmos = _showGizmos != T3.Core.Operator.GizmoVisibility.Off; + if (CustomComponents.ToggleIconButton(Icon.Grid, "##gizmos", ref showGizmos, Vector2.One * ImGui.GetFrameHeight() * T3Ui.UiScaleFactor)) { - ShowGizmos = showGizmos + _showGizmos = showGizmos ? T3.Core.Operator.GizmoVisibility.On : T3.Core.Operator.GizmoVisibility.Off; } @@ -119,8 +124,6 @@ public void DrawToolbarItems() _camSelectionHandling.DrawCameraControlSelection(); ImGui.SameLine(); - - ImGui.Checkbox("ControlBackground", ref HasInteractionFocus); } public void ClearBackground() @@ -129,7 +132,7 @@ public void ClearBackground() HasInteractionFocus = false; } - public GizmoVisibility ShowGizmos; + private GizmoVisibility _showGizmos; private readonly ImageOutputCanvas _imageCanvas = new(); private readonly CameraSelectionHandling _camSelectionHandling = new(); diff --git a/Editor/Gui/Graph/GraphNode.cs b/Editor/Gui/Graph/GraphNode.cs index 8eb2489e55..a862279cf8 100644 --- a/Editor/Gui/Graph/GraphNode.cs +++ b/Editor/Gui/Graph/GraphNode.cs @@ -23,6 +23,7 @@ using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.Windows; +using T3.Editor.UiModel; using Color = T3.Editor.Gui.Styling.Color; using Vector2 = System.Numerics.Vector2; using Vector3 = System.Numerics.Vector3; @@ -75,12 +76,24 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn var statusLevel = statusProvider.GetStatusLevel(); if (statusLevel == IStatusProvider.StatusLevel.Warning || statusLevel ==IStatusProvider.StatusLevel.Error) { - ImGui.SetCursorScreenPos(_usableScreenRect.Min - new Vector2(10, 10) * T3Ui.UiScaleFactor); + ImGui.SetCursorScreenPos(_usableScreenRect.Min - new Vector2(10, 12) * T3Ui.UiScaleFactor); ImGui.InvisibleButton("#warning", new Vector2(15, 15)); Icons.DrawIconOnLastItem(Icon.Warning, UiColors.StatusWarning); CustomComponents.TooltipForLastItem( UiColors.StatusWarning, statusLevel.ToString(), statusProvider.GetStatusMessage(), false); } } + + if (!string.IsNullOrEmpty(childUi.Comment)) + { + ImGui.SetCursorScreenPos(new Vector2(_usableScreenRect.Max.X, _usableScreenRect.Min.Y) - new Vector2(3, 12) * T3Ui.UiScaleFactor * T3Ui.UiScaleFactor); + if (ImGui.InvisibleButton("#comment", new Vector2(15, 15))) + { + NodeSelection.SetSelectionToChildUi(childUi,instance); + GraphCanvas.EditCommentDialog.ShowNextFrame(); + } + Icons.DrawIconOnLastItem(Icon.Comment, UiColors.ForegroundFull); + CustomComponents.TooltipForLastItem( UiColors.Text, childUi.Comment, null, false); + } // Resize indicator if (childUi.Style == SymbolChildUi.Styles.Resizable) @@ -211,24 +224,29 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn && !ImGui.IsMouseDragging(ImGuiMouseButton.Left) && !RenameInstanceOverlay.IsOpen) { - ImGui.SetNextWindowSizeConstraints(new Vector2(200, 120), new Vector2(200, 120)); ImGui.BeginTooltip(); { - TransformGizmoHandling.SetDrawList(drawList); - _imageCanvasForTooltips.Update(); - _imageCanvasForTooltips.SetAsCurrent(); - if (instance.Outputs.Count > 0) + ImGui.SetNextWindowSizeConstraints(new Vector2(200, 200*9/16f), new Vector2(200, 200*9/16f)); + ImGui.BeginChild("##innerTooltip"); { - var firstOutput = instance.Outputs[0]; - IOutputUi outputUi = symbolUi.OutputUis[firstOutput.Id]; - _evaluationContext.Reset(); - _evaluationContext.RequestedResolution = new Size2(1280 / 2, 720 / 2); - outputUi.DrawValue(firstOutput, _evaluationContext, - recompute: UserSettings.Config.HoverMode == GraphCanvas.HoverModes.Live); + TransformGizmoHandling.SetDrawList(drawList); + _imageCanvasForTooltips.Update(); + _imageCanvasForTooltips.SetAsCurrent(); + if (instance.Outputs.Count > 0) + { + var firstOutput = instance.Outputs[0]; + IOutputUi outputUi = symbolUi.OutputUis[firstOutput.Id]; + _evaluationContext.Reset(); + _evaluationContext.RequestedResolution = new Size2(1280 / 2, 720 / 2); + outputUi.DrawValue(firstOutput, _evaluationContext, + recompute: UserSettings.Config.HoverMode == GraphCanvas.HoverModes.Live); + + } + _imageCanvasForTooltips.Deactivate(); + TransformGizmoHandling.RestoreDrawList(); } + ImGui.EndChild(); - _imageCanvasForTooltips.Deactivate(); - TransformGizmoHandling.RestoreDrawList(); } ImGui.EndTooltip(); } @@ -259,6 +277,7 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn { var count = Structure.CollectDependingSymbols(instance.Symbol).Count(); LibWarningDialog.DependencyCount = count; + LibWarningDialog.HandledInstance = instance; GraphCanvas.LibWarningDialog.ShowNextFrame(); blocked = true; } @@ -336,14 +355,18 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn && _selectableScreenRect.GetHeight() > 8) { drawList.PushClipRect(_usableScreenRect.Min, _usableScreenRect.Max, true); - ImGui.PushFont(GraphCanvas.Current.Scale.X < 1 * T3Ui.UiScaleFactor ? Fonts.FontSmall : Fonts.FontBold); + var useSmallFont = GraphCanvas.Current.Scale.X < 1 * T3Ui.UiScaleFactor; + var font = Fonts.FontBold; + var isRenamed = !string.IsNullOrEmpty(childUi.SymbolChild.Name); - - - drawList.AddText(_usableScreenRect.Min + LabelPos, - ColorVariations.OperatorLabel.Apply(typeColor), - isRenamed ? $"\"{childUi.SymbolChild.ReadableName}\"" : childUi.SymbolChild.ReadableName); - ImGui.PopFont(); + var fade = MathUtils.SmootherStep(0.2f, 0.6f, GraphCanvas.Current.Scale.X); + + drawList.AddText(font, + font.FontSize * ( useSmallFont ? GraphCanvas.Current.Scale.X : 1) * T3Ui.UiScaleFactor, + _usableScreenRect.Min + LabelPos, + ColorVariations.OperatorLabel.Apply(typeColor).Fade(fade), + isRenamed ? $"\"{childUi.SymbolChild.ReadableName}\"" : childUi.SymbolChild.ReadableName); + drawList.PopClipRect(); } @@ -426,7 +449,9 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn _drawList.PushClipRect(_usableScreenRect.Min, _usableScreenRect.Max, true); } - _drawList.AddText(screenCursor, valueColor, valueAsString); + if(!string.IsNullOrEmpty(valueAsString)) + _drawList.AddText(screenCursor, valueColor, valueAsString); + if (needClipping) _drawList.PopClipRect(); @@ -594,11 +619,11 @@ public static void Draw(SymbolChildUi childUi, Instance instance, bool preventIn var center = new Vector2(usableArea.Max.X + 2*r, usableArea.GetCenter().Y - 3*r); if (output.DirtyFlag.Trigger == DirtyFlagTrigger.Always) { - _drawList.AddCircle(center, r, colorForType); + _drawList.AddCircle(center, r, colorForType,3); } else if (output.DirtyFlag.Trigger == DirtyFlagTrigger.Animated) { - _drawList.AddCircleFilled(center, r, colorForType); + _drawList.AddCircleFilled(center, r, colorForType, 3); } } @@ -937,6 +962,9 @@ private static void DrawOutput(SymbolChildUi childUi, Symbol.OutputDefinition ou private static Guid _draggedOutputOpId; private static Guid _draggedOutputDefId; + private static Guid _draggedInputOpId; + private static Guid _draggedInputDefId; + private static ImRect GetUsableOutputSlotArea(SymbolChildUi targetUi, int outputIndex) { var thickness = (int)MathUtils.RemapAndClamp(GraphCanvas.Current.Scale.X, 0.5f, 1.2f, (int)(UsableSlotThickness * 0.5f), UsableSlotThickness); @@ -1018,7 +1046,7 @@ private static void DrawInputSlot(SymbolChildUi targetUi, Symbol.InputDefinition } ImGui.EndTooltip(); - if (ImGui.IsItemClicked(0)) + if (ImGui.IsItemClicked(ImGuiMouseButton.Left)) { var createCopy = ImGui.GetIO().KeyCtrl && connection != null; if (createCopy) @@ -1043,11 +1071,40 @@ private static void DrawInputSlot(SymbolChildUi targetUi, Symbol.InputDefinition } else { - ConnectionMaker.StartFromInputSlot(GraphCanvas.Current.CompositionOp.Symbol, targetUi, inputDef); + _draggedInputOpId = targetUi.Id; + _draggedInputDefId = inputDef.Id; + } + } + else + { + if (ImGui.IsMouseReleased(ImGuiMouseButton.Left)) + { + _draggedInputOpId = Guid.Empty; + _draggedInputDefId = Guid.Empty; + if (ImGui.GetMouseDragDelta().Length() < UserSettings.Config.ClickThreshold) + { + ConnectionMaker.StartFromInputSlot(targetUi.SymbolChild.Parent, targetUi, inputDef); + var freePosition = NodeGraphLayouting.FindPositionForNodeConnectedToInput(targetUi.SymbolChild.Parent, targetUi, inputDef); + ConnectionMaker.InitSymbolBrowserOnPrimaryGraphWindow(freePosition); + } + else if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && ImGui.GetIO().KeyCtrl) + { + ConnectionMaker.StartFromInputSlot(GraphCanvas.Current.CompositionOp.Symbol, targetUi, inputDef); + } } } } } + else if (_draggedInputOpId == targetUi.Id && _draggedInputDefId == inputDef.Id) + { + if (ImGui.IsMouseDragging(ImGuiMouseButton.Left) + && ImGui.GetMouseDragDelta().Length() > UserSettings.Config.ClickThreshold) + { + _draggedInputOpId = Guid.Empty; + _draggedInputDefId = Guid.Empty; + ConnectionMaker.StartFromInputSlot(GraphCanvas.Current.CompositionOp.Symbol, targetUi, inputDef); + } + } else { var connectionColor = GetReactiveSlotColor(inputDef.DefaultValue.ValueType, colorForType, SocketDirections.Input); diff --git a/Editor/Gui/Graph/GraphWindow.cs b/Editor/Gui/Graph/GraphWindow.cs index ffd8f234ca..00a84f09ee 100644 --- a/Editor/Gui/Graph/GraphWindow.cs +++ b/Editor/Gui/Graph/GraphWindow.cs @@ -16,6 +16,7 @@ using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.Windows; using T3.Editor.Gui.Windows.TimeLine; +using T3.Editor.UiModel; using Vector2 = System.Numerics.Vector2; namespace T3.Editor.Gui.Graph @@ -46,11 +47,11 @@ public GraphWindow() public static bool CanOpenAnotherWindow() { - if (_instanceCounter > 0) - { - //Log.Error("only one graph window supported for now"); - return false; - } + // if (_instanceCounter > 0) + // { + // //Log.Error("only one graph window supported for now"); + // return false; + // } return true; } @@ -418,6 +419,7 @@ private static void DrawMiniMap(Instance compositionOp, ScalableCanvas canvas) private void DrawControlsAtBottom() { + TimeControls.HandleTimeControlActions(); if (!UserSettings.Config.ShowToolbar) return; diff --git a/Editor/Gui/Graph/Helpers/Structure.cs b/Editor/Gui/Graph/Helpers/Structure.cs index 2a539d5884..2fb00f8cce 100644 --- a/Editor/Gui/Graph/Helpers/Structure.cs +++ b/Editor/Gui/Graph/Helpers/Structure.cs @@ -6,6 +6,7 @@ using T3.Core.Operator; using T3.Core.Operator.Slots; using T3.Core.Utils; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Helpers; diff --git a/Editor/Gui/Graph/Interaction/Connections/ConnectionMaker.cs b/Editor/Gui/Graph/Interaction/Connections/ConnectionMaker.cs index d3a53e08b3..c81149d120 100644 --- a/Editor/Gui/Graph/Interaction/Connections/ConnectionMaker.cs +++ b/Editor/Gui/Graph/Interaction/Connections/ConnectionMaker.cs @@ -9,6 +9,7 @@ using T3.Editor.Gui.Graph.Helpers; using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Selection; +using T3.Editor.UiModel; using Vector2 = System.Numerics.Vector2; namespace T3.Editor.Gui.Graph.Interaction.Connections @@ -74,8 +75,8 @@ public static void StartFromOutputSlot(Symbol parentSymbol, SymbolChildUi source var selectedSymbolChildUis = NodeSelection.GetSelectedChildUis().OrderBy(c => c.PosOnCanvas.Y * 100 + c.PosOnCanvas.X).ToList(); selectedSymbolChildUis.Reverse(); - //if (selectedSymbolChildUis.Count > 1 && selectedSymbolChildUis.Any(c => c.Id == sourceUi.Id)) - if (selectedSymbolChildUis.Count > 1) + if (selectedSymbolChildUis.Count > 1 && (selectedSymbolChildUis.Any(c => c.Id == sourceUi.Id))) + //if (selectedSymbolChildUis.Count > 1) { selectedSymbolChildUis.Reverse(); @@ -161,6 +162,7 @@ public static void StartFromOutputNode(Symbol parentSymbol, Symbol.OutputDefinit targetParentOrChildId: NotConnectedId, targetSlotId: NotConnectedId, outputDef.ValueType)); + _isDisconnectingFromInput = true; } else { @@ -169,6 +171,7 @@ public static void StartFromOutputNode(Symbol parentSymbol, Symbol.OutputDefinit targetParentOrChildId: UseSymbolContainerId, targetSlotId: outputDef.Id, outputDef.ValueType)); + _isDisconnectingFromInput = false; } } @@ -512,42 +515,7 @@ public static void InitSymbolBrowserAtPosition(SymbolBrowser symbolBrowser, Vect AbortOperation(); } } - - // public static void CompleteConnectsToBuiltNode(Symbol parent, SymbolChild newSymbolChild) - // { - // foreach (var c in TempConnections) - // { - // switch (c.GetStatus()) - // { - // case TempConnection.Status.SourceIsDraftNode: - // var outputDef = newSymbolChild.Symbol.GetOutputMatchingType(c.ConnectionType); - // var newConnectionToSource = new Symbol.Connection(sourceParentOrChildId: newSymbolChild.Id, - // sourceSlotId: outputDef.Id, - // targetParentOrChildId: c.TargetParentOrChildId, - // targetSlotId: c.TargetSlotId); - // UndoRedoStack.AddAndExecute(new AddConnectionCommand(parent, newConnectionToSource, 0)); - // break; - // - // case TempConnection.Status.TargetIsDraftNode: - // var inputDef = newSymbolChild.Symbol.GetInputMatchingType(c.ConnectionType); - // if (inputDef == null) - // { - // Log.Warning("Failed to complete node creation"); - // Reset(); - // return; - // } - // - // var newConnectionToInput = new Symbol.Connection(sourceParentOrChildId: c.SourceParentOrChildId, - // sourceSlotId: c.SourceSlotId, - // targetParentOrChildId: newSymbolChild.Id, - // targetSlotId: inputDef.Id); - // UndoRedoStack.AddAndExecute(new AddConnectionCommand(parent, newConnectionToInput, 0)); - // break; - // } - // } - // - // Reset(); - // } + public static void OpenSymbolBrowserAtOutput(SymbolBrowser symbolBrowser, SymbolChildUi childUi, Instance instance, Guid outputId) @@ -560,21 +528,31 @@ public static void OpenSymbolBrowserAtOutput(SymbolBrowser symbolBrowser, Symbol InsertSymbolBrowser(symbolBrowser, childUi, instance, primaryOutput); } - public static void OpenBrowserWithSingleSelection(SymbolBrowser symbolBrowser, SymbolChildUi childUi, Instance instance) + public static void InsertSymbolInstance(Symbol symbol) { + var instance = NodeSelection.GetSelectedInstance(); + if (instance == null) + { + return; + } + + + var parentUi = SymbolUiRegistry.Entries[instance.Parent.Symbol.Id]; + var symbolChildUi = parentUi.ChildUis.FirstOrDefault(c => c.Id == instance.SymbolChildId); + + if (symbolChildUi == null) + { + return; + } + + if (instance.Outputs.Count < 1) return; - //StartOperation("Insert Operator"); - var primaryOutput = instance.Outputs[0]; + var posOnCanvas = symbolChildUi.PosOnCanvas; - InsertSymbolBrowser(symbolBrowser, childUi, instance, primaryOutput); - } - - private static void InsertSymbolBrowser(SymbolBrowser symbolBrowser, SymbolChildUi childUi, Instance instance, ISlot primaryOutput) - { + var primaryOutput = instance.Outputs[0]; StartOperation("Insert Operator"); - var connections = instance.Parent.Symbol.Connections.FindAll(connection => connection.SourceParentOrChildId == instance.SymbolChildId && connection.SourceSlotId == primaryOutput.Id); @@ -584,7 +562,6 @@ private static void InsertSymbolBrowser(SymbolBrowser symbolBrowser, SymbolChild targetSlotId: NotConnectedId, primaryOutput.ValueType)); - Type filterOutputType = null; if (connections.Count > 0) { AdjustGraphLayoutForNewNode(instance.Parent.Symbol, connections[0]); @@ -598,7 +575,136 @@ private static void InsertSymbolBrowser(SymbolBrowser symbolBrowser, SymbolChild targetSlotId: oldConnection.TargetSlotId, primaryOutput.ValueType, multiInputIndex)); - filterOutputType = primaryOutput.ValueType; + } + } + else + { + posOnCanvas.X += SymbolChildUi.DefaultOpSize.X + SelectableNodeMovement.SnapPadding.X; + } + + var commandsForUndo = new List(); + var parentSymbol = instance.Parent.Symbol; + + var addSymbolChildCommand = new AddSymbolChildCommand(parentSymbol, symbol.Id) { PosOnCanvas = posOnCanvas }; + commandsForUndo.Add(addSymbolChildCommand); + addSymbolChildCommand.Do(); + var newSymbolChild = parentSymbol.Children.Single(entry => entry.Id == addSymbolChildCommand.AddedChildId); + + // Select new node + var symbolUi = SymbolUiRegistry.Entries[parentSymbol.Id]; + var newChildUi = symbolUi.ChildUis.Find(s => s.Id == newSymbolChild.Id); + if (newChildUi == null) + { + Log.Warning("Unable to create new operator"); + return; + } + + var newInstance = instance.Parent.Children.Single(child => child.SymbolChildId == newChildUi.Id); + + NodeSelection.SetSelectionToChildUi(newChildUi, newInstance); + + foreach (var c in ConnectionMaker.TempConnections) + { + switch (c.GetStatus()) + { + case ConnectionMaker.TempConnection.Status.SourceIsDraftNode: + var outputDef = newSymbolChild.Symbol.GetOutputMatchingType(c.ConnectionType); + if (outputDef == null) + { + Log.Error("Failed to find matching output connection type " + c.ConnectionType); + continue; + } + + + var newConnectionToSource = new Symbol.Connection(sourceParentOrChildId: newSymbolChild.Id, + sourceSlotId: outputDef.Id, + targetParentOrChildId: c.TargetParentOrChildId, + targetSlotId: c.TargetSlotId); + var addConnectionCommand = new AddConnectionCommand(parentSymbol, newConnectionToSource, c.MultiInputIndex); + addConnectionCommand.Do(); + commandsForUndo.Add(addConnectionCommand); + break; + + case ConnectionMaker.TempConnection.Status.TargetIsDraftNode: + var inputDef = newSymbolChild.Symbol.GetInputMatchingType(c.ConnectionType); + if (inputDef == null) + { + Log.Warning("Failed to complete node creation"); + continue; + } + + var newConnectionToInput = new Symbol.Connection(sourceParentOrChildId: c.SourceParentOrChildId, + sourceSlotId: c.SourceSlotId, + targetParentOrChildId: newSymbolChild.Id, + targetSlotId: inputDef.Id); + var connectionCommand = new AddConnectionCommand(parentSymbol, newConnectionToInput, c.MultiInputIndex); + connectionCommand.Do(); + commandsForUndo.Add(connectionCommand); + break; + } + } + + CompleteOperation(commandsForUndo, "Insert Op " + newChildUi.SymbolChild.ReadableName); + ParameterPopUp.NodeIdRequestedForParameterWindowActivation = newSymbolChild.Id; + } + + public static void OpenBrowserWithSingleSelection(SymbolBrowser symbolBrowser, SymbolChildUi childUi, Instance instance) + { + if (instance.Outputs.Count < 1) + return; + + //StartOperation("Insert Operator"); + var primaryOutput = instance.Outputs[0]; + + InsertSymbolBrowser(symbolBrowser, childUi, instance, primaryOutput); + } + + private static void InsertSymbolBrowser(SymbolBrowser symbolBrowser, SymbolChildUi childUi, Instance instance, ISlot primaryOutput) + { + StartOperation("Insert Operator"); + + var connections = instance.Parent.Symbol.Connections.FindAll(connection => connection.SourceParentOrChildId == instance.SymbolChildId + && connection.SourceSlotId == primaryOutput.Id); + + TempConnections.Add(new TempConnection(sourceParentOrChildId: instance.SymbolChildId, + sourceSlotId: primaryOutput.Id, + targetParentOrChildId: UseDraftChildId, + targetSlotId: NotConnectedId, + primaryOutput.ValueType)); + + + Type filterOutputType = null; + if (connections.Count > 0) + { + var mainConnection = connections[0]; + if (mainConnection.IsConnectedToSymbolOutput) + { + var compId = instance.Parent.Symbol.Id; + var compUi = SymbolUiRegistry.Entries[compId]; + + if(compUi.OutputUis.TryGetValue(mainConnection.TargetSlotId, out var outputUi)) + { + var moveCommand = new ModifyCanvasElementsCommand(compId, new List() {outputUi}); + outputUi.PosOnCanvas += new Vector2(SymbolChildUi.DefaultOpSize.X, 0); + moveCommand.StoreCurrentValues(); + _inProgressCommand.AddAndExecCommand(moveCommand); + } + } + else + { + AdjustGraphLayoutForNewNode(instance.Parent.Symbol, mainConnection); + foreach (var oldConnection in connections) + { + var multiInputIndex = instance.Parent.Symbol.GetMultiInputIndexFor(oldConnection); + _inProgressCommand.AddAndExecCommand(new DeleteConnectionCommand(instance.Parent.Symbol, oldConnection, multiInputIndex)); + TempConnections.Add(new TempConnection(sourceParentOrChildId: UseDraftChildId, + sourceSlotId: NotConnectedId, + targetParentOrChildId: oldConnection.TargetParentOrChildId, + targetSlotId: oldConnection.TargetSlotId, + primaryOutput.ValueType, + multiInputIndex)); + filterOutputType = primaryOutput.ValueType; + } } } diff --git a/Editor/Gui/Graph/Interaction/Connections/ConnectionSnapEndHelper.cs b/Editor/Gui/Graph/Interaction/Connections/ConnectionSnapEndHelper.cs index 9327937c27..0ae2d35b97 100644 --- a/Editor/Gui/Graph/Interaction/Connections/ConnectionSnapEndHelper.cs +++ b/Editor/Gui/Graph/Interaction/Connections/ConnectionSnapEndHelper.cs @@ -5,6 +5,7 @@ using T3.Editor.Gui.InputUi; using T3.Editor.Gui.OutputUi; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction.Connections { diff --git a/Editor/Gui/Graph/Interaction/Connections/ConnectionSplitHelper.cs b/Editor/Gui/Graph/Interaction/Connections/ConnectionSplitHelper.cs index bc71f80fe5..2905c73b20 100644 --- a/Editor/Gui/Graph/Interaction/Connections/ConnectionSplitHelper.cs +++ b/Editor/Gui/Graph/Interaction/Connections/ConnectionSplitHelper.cs @@ -9,6 +9,7 @@ using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.Windows; +using T3.Editor.UiModel; using Color = T3.Editor.Gui.Styling.Color; using Vector2 = System.Numerics.Vector2; @@ -77,17 +78,13 @@ public static void PrepareNewFrame(GraphCanvas graphCanvas) if (outputSlot != null && output != null && input != null) { - ImGui.PushFont(Fonts.FontSmall); - var connectionSource = sourceOp.ReadableName + "." + output.OutputDefinition.Name; - ImGui.TextColored(UiColors.Gray, connectionSource); - - var connectionTarget = "->" + targetOp.ReadableName + "." + input.InputDefinition.Name; - ImGui.TextColored(UiColors.Gray, connectionTarget); - ImGui.PopFont(); var width = 160f; + ImGui.SetNextWindowSizeConstraints(new Vector2(200, 200*9/16f), new Vector2(200, 200*9/16f)); + ImGui.BeginChild("thumbnail", new Vector2(width, width * 9 / 16f)); { + TransformGizmoHandling.SetDrawList(drawList); ImageCanvasForTooltips.Update(); ImageCanvasForTooltips.SetAsCurrent(); @@ -99,20 +96,30 @@ public static void PrepareNewFrame(GraphCanvas graphCanvas) EvaluationContext.RequestedResolution = new Size2(1280 / 2, 720 / 2); outputUi.DrawValue(outputSlot, EvaluationContext, recompute: UserSettings.Config.HoverMode == GraphCanvas.HoverModes.Live); - if (!string.IsNullOrEmpty(sourceOpUi.Description)) - { - ImGui.Spacing(); - ImGui.PushFont(Fonts.FontSmall); - ImGui.PushStyleColor(ImGuiCol.Text, new Color(1, 1, 1, 0.5f).Rgba); - ImGui.TextWrapped(sourceOpUi.Description); - ImGui.PopStyleColor(); - ImGui.PopFont(); - } + // if (!string.IsNullOrEmpty(sourceOpUi.Description)) + // { + // ImGui.Spacing(); + // ImGui.PushFont(Fonts.FontSmall); + // ImGui.PushStyleColor(ImGuiCol.Text, new Color(1, 1, 1, 0.5f).Rgba); + // ImGui.TextWrapped(sourceOpUi.Description); + // ImGui.PopStyleColor(); + // ImGui.PopFont(); + // } ImageCanvasForTooltips.Deactivate(); TransformGizmoHandling.RestoreDrawList(); } ImGui.EndChild(); + ImGui.PushFont(Fonts.FontSmall); + var type = output.OutputDefinition.ValueType; + var connectionSource = sourceOp.ReadableName + "." + output.OutputDefinition.Name; + ImGui.TextColored(UiColors.TextMuted, connectionSource); + + ImGui.TextUnformatted(type.Name); + ImGui.SameLine(); + var connectionTarget = "--> " + targetOp.ReadableName + "." + input.InputDefinition.Name; + ImGui.TextColored(UiColors.TextMuted, connectionTarget); + ImGui.PopFont(); FrameStats.AddHoveredId(targetOp.Id); FrameStats.AddHoveredId(sourceOp.Id); @@ -151,7 +158,7 @@ public static void RegisterAsPotentialSplit(Symbol.Connection connection, Color _bestMatchDistance = distance; } - private static readonly ImageOutputCanvas ImageCanvasForTooltips = new ImageOutputCanvas(); + private static readonly ImageOutputCanvas ImageCanvasForTooltips = new() { DisableDamping = true }; private static readonly EvaluationContext EvaluationContext = new EvaluationContext(); public static PotentialConnectionSplit BestMatchLastFrame; diff --git a/Editor/Gui/Graph/Interaction/ExampleSymbolLinking.cs b/Editor/Gui/Graph/Interaction/ExampleSymbolLinking.cs index 10d76161ae..5658b21da2 100644 --- a/Editor/Gui/Graph/Interaction/ExampleSymbolLinking.cs +++ b/Editor/Gui/Graph/Interaction/ExampleSymbolLinking.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using T3.Core.Logging; using T3.Core.Operator; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { diff --git a/Editor/Gui/Graph/Interaction/FileReferenceOperations.cs b/Editor/Gui/Graph/Interaction/FileReferenceOperations.cs index d992d3354a..21dea3c1ba 100644 --- a/Editor/Gui/Graph/Interaction/FileReferenceOperations.cs +++ b/Editor/Gui/Graph/Interaction/FileReferenceOperations.cs @@ -6,58 +6,33 @@ using T3.Core.Operator.Slots; using T3.Core.Resource; using T3.Editor.Gui.InputUi.SimpleInputUis; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { public class FileReferenceOperations { - private static void FindMissingPathsInSymbol(Symbol symbol) + public static void FixOperatorFilepathsCommand_Executed() { - foreach (var symbolChild in symbol.Children) + AssetFiles.Clear(); + ScanAssetDirectory(ResourceManager.ResourcesFolder); + foreach (var ( key, value) in AssetFiles) { - //var symbolUi = SymbolUiRegistry.Entries[symbol.Id]; + Log.Debug($"found {key} in {value}"); + } - foreach (var input in symbolChild.Symbol.InputDefinitions) + + foreach (var symbol in SymbolRegistry.Entries.Values) + { + var symbolUpdated = FindMissingPathsInSymbol(symbol); + if (symbolUpdated) { - var symbolChildUi = SymbolUiRegistry.Entries[symbolChild.Symbol.Id]; - var inputUi = symbolChildUi.InputUis[input.Id]; - if (!(inputUi is StringInputUi stringInputUi)) - continue; - - if (stringInputUi.Usage != StringInputUi.UsageType.FilePath) - continue; - - if (!symbolChild.Inputs.ContainsKey(input.Id)) - continue; - var inputValue = symbolChild.Inputs[input.Id].IsDefault - ? symbolChild.Inputs[input.Id].DefaultValue - : symbolChild.Inputs[input.Id].Value; - - var stringInputValue = inputValue as InputValue; - if (stringInputValue == null) - continue; - - var path = stringInputValue.Value; - - if (string.IsNullOrEmpty(path)) - continue; - - if (File.Exists(path)) - continue; - - Log.Warning($"Missing File: {path} in {symbol.Name}/{symbolChild.ReadableName}.{input.Name}", symbolChild.Id); - var basename = Path.GetFileName(path); - - if (!AssetFiles.ContainsKey(basename)) - continue; - - Log.Info($" -> fixed with: {AssetFiles[basename]}"); - stringInputValue.Value =AssetFiles[basename]; } } } + private static void ScanAssetDirectory(string path) { string[] files = new string[0]; @@ -92,23 +67,57 @@ private static void ScanAssetDirectory(string path) ScanAssetDirectory(path + "\\" + dirname); } } - - public static void FixOperatorFilepathsCommand_Executed() + + private static bool FindMissingPathsInSymbol(Symbol symbol) { - AssetFiles.Clear(); - ScanAssetDirectory(ResourceManager.ResourcesFolder); - foreach (var ( key, value) in AssetFiles) + var symbolUpdated = false; + foreach (var symbolChild in symbol.Children) { - Log.Debug($"found {key} in {value}"); - } + foreach (var input in symbolChild.Symbol.InputDefinitions) + { + var symbolChildUi = SymbolUiRegistry.Entries[symbolChild.Symbol.Id]; + var inputUi = symbolChildUi.InputUis[input.Id]; + if (inputUi is not StringInputUi stringInputUi) + continue; - - foreach (var symbol in SymbolRegistry.Entries.Values) - { - FindMissingPathsInSymbol(symbol); + if (stringInputUi.Usage != StringInputUi.UsageType.FilePath) + continue; + + if (!symbolChild.Inputs.ContainsKey(input.Id)) + continue; + + var inputValue = symbolChild.Inputs[input.Id].IsDefault + ? symbolChild.Inputs[input.Id].DefaultValue + : symbolChild.Inputs[input.Id].Value; + + var stringInputValue = inputValue as InputValue; + if (stringInputValue == null) + continue; + + var path = stringInputValue.Value; + + if (string.IsNullOrEmpty(path)) + continue; + + if (File.Exists(path)) + continue; + + Log.Warning($"Missing File: {path} in {symbol.Name}/{symbolChild.ReadableName}.{input.Name}", symbolChild.Id); + var basename = Path.GetFileName(path); + + if (!AssetFiles.ContainsKey(basename)) + continue; + + Log.Info($" -> fixed with: {AssetFiles[basename]}"); + stringInputValue.Value =AssetFiles[basename]; + symbol.InvalidateInputInAllChildInstances(input.Id, symbolChild.Id); + symbolUpdated = true; + } } - } + return symbolUpdated; + } + private static readonly Dictionary AssetFiles = new Dictionary(); } } \ No newline at end of file diff --git a/Editor/Gui/Graph/Interaction/NodeGraphLayouting.cs b/Editor/Gui/Graph/Interaction/NodeGraphLayouting.cs index 16aa77776a..3459595607 100644 --- a/Editor/Gui/Graph/Interaction/NodeGraphLayouting.cs +++ b/Editor/Gui/Graph/Interaction/NodeGraphLayouting.cs @@ -9,6 +9,7 @@ using T3.Editor.Gui.Graph.Helpers; using T3.Editor.Gui.Selection; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction; diff --git a/Editor/Gui/Graph/Interaction/NodeNavigation.cs b/Editor/Gui/Graph/Interaction/NodeNavigation.cs index 63b5230d55..ce2a8da2d5 100644 --- a/Editor/Gui/Graph/Interaction/NodeNavigation.cs +++ b/Editor/Gui/Graph/Interaction/NodeNavigation.cs @@ -6,6 +6,7 @@ using T3.Core.Utils; using T3.Editor.Gui.Graph.Helpers; using T3.Editor.Gui.Windows; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction; diff --git a/Editor/Gui/Graph/Interaction/NodeSelection.cs b/Editor/Gui/Graph/Interaction/NodeSelection.cs index 5ec21ef66f..117b6cf103 100644 --- a/Editor/Gui/Graph/Interaction/NodeSelection.cs +++ b/Editor/Gui/Graph/Interaction/NodeSelection.cs @@ -8,6 +8,7 @@ using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Interaction.TransformGizmos; using T3.Editor.Gui.Selection; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { diff --git a/Editor/Gui/Graph/Interaction/ParameterExtraction.cs b/Editor/Gui/Graph/Interaction/ParameterExtraction.cs index 12d8d5fabe..0c18531fcf 100644 --- a/Editor/Gui/Graph/Interaction/ParameterExtraction.cs +++ b/Editor/Gui/Graph/Interaction/ParameterExtraction.cs @@ -1,165 +1,166 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using T3.Core.DataTypes; -using T3.Core.Logging; -using T3.Core.Operator; -using T3.Core.Operator.Slots; -using T3.Editor.Gui.Commands; -using T3.Editor.Gui.Commands.Graph; -using T3.Operators.Types.Id_5880cbc3_a541_4484_a06a_0e6f77cdbe8e; -using T3.Operators.Types.Id_5d7d61ae_0a41_4ffa_a51d_93bab665e7fe; -using T3.Operators.Types.Id_8211249d_7a26_4ad0_8d84_56da72a5c536; -using T3.Operators.Types.Id_926ab3fd_fbaf_4c4b_91bc_af277000dcb8; -using T3.Operators.Types.Id_94a5de3b_ee6a_43d3_8d21_7b8fe94b042b; -using T3.Operators.Types.Id_cc07b314_4582_4c2c_84b8_bb32f59fc09b; - -namespace T3.Editor.Gui.Graph.Interaction; - -internal static class ParameterExtraction -{ - public static bool IsInputSlotExtractable(IInputSlot inputSlot) - { - return _symbolIdsForTypes.ContainsKey(inputSlot.ValueType); - } - - public static void ExtractAsConnectedOperator(IInputSlot inputSlot, SymbolChildUi symbolChildUi, SymbolChild.Input input) - { - var composition = NodeSelection.GetSelectedComposition() ?? inputSlot.Parent.Parent; - if (composition == null) - { - Log.Warning("Can't publish input to undefined composition"); - return; - } - - var compositionSymbol = composition.Symbol; - var commands = new List(); - - // Find matching symbol - if (!_symbolIdsForTypes.TryGetValue(input.DefaultValue.ValueType, out var symbolId)) - { - Log.Warning("Can't extract this parameter type"); - return; - } - - var symbol = SymbolRegistry.Entries[symbolId]; - - // Add Child - var freePosition = NodeGraphLayouting.FindPositionForNodeConnectedToInput(compositionSymbol, symbolChildUi, input.InputDefinition); - var addSymbolChildCommand = new AddSymbolChildCommand(compositionSymbol, symbol.Id) - { - PosOnCanvas = freePosition, - ChildName = input.Name - }; - if (_sizesForTypes.TryGetValue(input.DefaultValue.ValueType, out var sizeOverride)) - { - addSymbolChildCommand.Size = sizeOverride; // FIXME: doesn't seem to have an effect - } - - commands.Add(addSymbolChildCommand); - addSymbolChildCommand.Do(); - - var newSymbolChild = compositionSymbol.Children.Single(entry => entry.Id == addSymbolChildCommand.AddedChildId); - - var symbolUi = SymbolUiRegistry.Entries[compositionSymbol.Id]; - var newChildUi = symbolUi.ChildUis.Find(s => s.Id == newSymbolChild.Id); - - // Sadly, we have have apply size manually. - if (_sizesForTypes.TryGetValue(input.DefaultValue.ValueType, out _)) - { - newChildUi.Style = SymbolChildUi.Styles.Resizable; - } - - if (newChildUi == null) - { - Log.Warning("Unable to create new operator"); - return; - } - - // Set type - var newInstance = composition.Children.Single(child => child.SymbolChildId == newChildUi.Id); - var inputsAndValues = new Dictionary(); - - switch (newInstance) - { - case Value valueInstance when inputSlot is InputSlot floatInput: - { - inputsAndValues[valueInstance.Float.Input] = floatInput.TypedInputValue; - break; - } - case IntValue intValueInstance when inputSlot is InputSlot intInput: - { - inputsAndValues[intValueInstance.Int.Input] = intInput.TypedInputValue; - break; - } - - case AString stringInstance when inputSlot is InputSlot stringInput: - { - inputsAndValues[stringInstance.InputString.Input] = stringInput.TypedInputValue; - break; - } - - case SampleGradient gradientInstance when inputSlot is InputSlot gradientInput: - { - inputsAndValues[gradientInstance.Gradient.Input] = gradientInput.TypedInputValue; - break; - } - - case Float2ToVector2 float2ToVector2 when inputSlot is InputSlot vec2: - { - inputsAndValues[float2ToVector2.X.Input] = new InputValue(vec2.TypedInputValue.Value.X); - inputsAndValues[float2ToVector2.Y.Input] = new InputValue(vec2.TypedInputValue.Value.Y); - break; - } - - case Float3ToVector3 float3ToVector3 when inputSlot is InputSlot vec3: - { - inputsAndValues[float3ToVector3.X.Input] = new InputValue(vec3.TypedInputValue.Value.X); - inputsAndValues[float3ToVector3.Y.Input] = new InputValue(vec3.TypedInputValue.Value.Y); - inputsAndValues[float3ToVector3.Z.Input] = new InputValue(vec3.TypedInputValue.Value.Z); - break; - } - } - - if (inputsAndValues.Count == 0) - { - Log.Warning("Failed to find matching types"); - return; - } - - foreach (var (typedInput, inputValue) in inputsAndValues) - { - var setValueCommand = new ChangeInputValueCommand(compositionSymbol, newSymbolChild.Id, typedInput, inputValue); - setValueCommand.Do(); - commands.Add(setValueCommand); - } - - // Create connection - var firstMatchingOutput = newSymbolChild.Symbol.OutputDefinitions.First(o => o.ValueType == input.DefaultValue.ValueType); - - var newConnection = new Symbol.Connection(sourceParentOrChildId: newSymbolChild.Id, - sourceSlotId: firstMatchingOutput.Id, - targetParentOrChildId: symbolChildUi.SymbolChild.Id, - targetSlotId: input.InputDefinition.Id); - var addConnectionCommand = new AddConnectionCommand(compositionSymbol, newConnection, 0); - addConnectionCommand.Do(); - commands.Add(addConnectionCommand); - UndoRedoStack.Add(new MacroCommand("Extract as operator", commands)); - } - - private static readonly Dictionary _symbolIdsForTypes = new() - { - { typeof(float), Guid.Parse("5d7d61ae-0a41-4ffa-a51d-93bab665e7fe") }, - { typeof(Vector2), Guid.Parse("926ab3fd-fbaf-4c4b-91bc-af277000dcb8") }, - { typeof(Vector3), Guid.Parse("94a5de3b-ee6a-43d3-8d21-7b8fe94b042b") }, - { typeof(string), Guid.Parse("5880cbc3-a541-4484-a06a-0e6f77cdbe8e") }, - { typeof(int), Guid.Parse("cc07b314-4582-4c2c-84b8-bb32f59fc09b") }, - { typeof(Gradient), Guid.Parse("8211249d-7a26-4ad0-8d84-56da72a5c536") }, - }; - - private static readonly Dictionary _sizesForTypes = new() - { - { typeof(string), new Vector2(120, 80) }, - }; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using T3.Core.DataTypes; +using T3.Core.Logging; +using T3.Core.Operator; +using T3.Core.Operator.Slots; +using T3.Editor.Gui.Commands; +using T3.Editor.Gui.Commands.Graph; +using T3.Editor.UiModel; +using T3.Operators.Types.Id_5880cbc3_a541_4484_a06a_0e6f77cdbe8e; +using T3.Operators.Types.Id_5d7d61ae_0a41_4ffa_a51d_93bab665e7fe; +using T3.Operators.Types.Id_8211249d_7a26_4ad0_8d84_56da72a5c536; +using T3.Operators.Types.Id_926ab3fd_fbaf_4c4b_91bc_af277000dcb8; +using T3.Operators.Types.Id_94a5de3b_ee6a_43d3_8d21_7b8fe94b042b; +using T3.Operators.Types.Id_cc07b314_4582_4c2c_84b8_bb32f59fc09b; + +namespace T3.Editor.Gui.Graph.Interaction; + +internal static class ParameterExtraction +{ + public static bool IsInputSlotExtractable(IInputSlot inputSlot) + { + return _symbolIdsForTypes.ContainsKey(inputSlot.ValueType); + } + + public static void ExtractAsConnectedOperator(IInputSlot inputSlot, SymbolChildUi symbolChildUi, SymbolChild.Input input) + { + var composition = NodeSelection.GetSelectedComposition() ?? inputSlot.Parent.Parent; + if (composition == null) + { + Log.Warning("Can't publish input to undefined composition"); + return; + } + + var compositionSymbol = composition.Symbol; + var commands = new List(); + + // Find matching symbol + if (!_symbolIdsForTypes.TryGetValue(input.DefaultValue.ValueType, out var symbolId)) + { + Log.Warning("Can't extract this parameter type"); + return; + } + + var symbol = SymbolRegistry.Entries[symbolId]; + + // Add Child + var freePosition = NodeGraphLayouting.FindPositionForNodeConnectedToInput(compositionSymbol, symbolChildUi, input.InputDefinition); + var addSymbolChildCommand = new AddSymbolChildCommand(compositionSymbol, symbol.Id) + { + PosOnCanvas = freePosition, + ChildName = input.Name + }; + if (_sizesForTypes.TryGetValue(input.DefaultValue.ValueType, out var sizeOverride)) + { + addSymbolChildCommand.Size = sizeOverride; // FIXME: doesn't seem to have an effect + } + + commands.Add(addSymbolChildCommand); + addSymbolChildCommand.Do(); + + var newSymbolChild = compositionSymbol.Children.Single(entry => entry.Id == addSymbolChildCommand.AddedChildId); + + var symbolUi = SymbolUiRegistry.Entries[compositionSymbol.Id]; + var newChildUi = symbolUi.ChildUis.Find(s => s.Id == newSymbolChild.Id); + + // Sadly, we have have apply size manually. + if (_sizesForTypes.TryGetValue(input.DefaultValue.ValueType, out _)) + { + newChildUi.Style = SymbolChildUi.Styles.Resizable; + } + + if (newChildUi == null) + { + Log.Warning("Unable to create new operator"); + return; + } + + // Set type + var newInstance = composition.Children.Single(child => child.SymbolChildId == newChildUi.Id); + var inputsAndValues = new Dictionary(); + + switch (newInstance) + { + case Value valueInstance when inputSlot is InputSlot floatInput: + { + inputsAndValues[valueInstance.Float.Input] = floatInput.TypedInputValue; + break; + } + case IntValue intValueInstance when inputSlot is InputSlot intInput: + { + inputsAndValues[intValueInstance.Int.Input] = intInput.TypedInputValue; + break; + } + + case AString stringInstance when inputSlot is InputSlot stringInput: + { + inputsAndValues[stringInstance.InputString.Input] = stringInput.TypedInputValue; + break; + } + + case SampleGradient gradientInstance when inputSlot is InputSlot gradientInput: + { + inputsAndValues[gradientInstance.Gradient.Input] = gradientInput.TypedInputValue; + break; + } + + case Float2ToVector2 float2ToVector2 when inputSlot is InputSlot vec2: + { + inputsAndValues[float2ToVector2.X.Input] = new InputValue(vec2.TypedInputValue.Value.X); + inputsAndValues[float2ToVector2.Y.Input] = new InputValue(vec2.TypedInputValue.Value.Y); + break; + } + + case Float3ToVector3 float3ToVector3 when inputSlot is InputSlot vec3: + { + inputsAndValues[float3ToVector3.X.Input] = new InputValue(vec3.TypedInputValue.Value.X); + inputsAndValues[float3ToVector3.Y.Input] = new InputValue(vec3.TypedInputValue.Value.Y); + inputsAndValues[float3ToVector3.Z.Input] = new InputValue(vec3.TypedInputValue.Value.Z); + break; + } + } + + if (inputsAndValues.Count == 0) + { + Log.Warning("Failed to find matching types"); + return; + } + + foreach (var (typedInput, inputValue) in inputsAndValues) + { + var setValueCommand = new ChangeInputValueCommand(compositionSymbol, newSymbolChild.Id, typedInput, inputValue); + setValueCommand.Do(); + commands.Add(setValueCommand); + } + + // Create connection + var firstMatchingOutput = newSymbolChild.Symbol.OutputDefinitions.First(o => o.ValueType == input.DefaultValue.ValueType); + + var newConnection = new Symbol.Connection(sourceParentOrChildId: newSymbolChild.Id, + sourceSlotId: firstMatchingOutput.Id, + targetParentOrChildId: symbolChildUi.SymbolChild.Id, + targetSlotId: input.InputDefinition.Id); + var addConnectionCommand = new AddConnectionCommand(compositionSymbol, newConnection, 0); + addConnectionCommand.Do(); + commands.Add(addConnectionCommand); + UndoRedoStack.Add(new MacroCommand("Extract as operator", commands)); + } + + private static readonly Dictionary _symbolIdsForTypes = new() + { + { typeof(float), Guid.Parse("5d7d61ae-0a41-4ffa-a51d-93bab665e7fe") }, + { typeof(Vector2), Guid.Parse("926ab3fd-fbaf-4c4b-91bc-af277000dcb8") }, + { typeof(Vector3), Guid.Parse("94a5de3b-ee6a-43d3-8d21-7b8fe94b042b") }, + { typeof(string), Guid.Parse("5880cbc3-a541-4484-a06a-0e6f77cdbe8e") }, + { typeof(int), Guid.Parse("cc07b314-4582-4c2c-84b8-bb32f59fc09b") }, + { typeof(Gradient), Guid.Parse("8211249d-7a26-4ad0-8d84-56da72a5c536") }, + }; + + private static readonly Dictionary _sizesForTypes = new() + { + { typeof(string), new Vector2(120, 80) }, + }; } \ No newline at end of file diff --git a/Editor/Gui/Graph/Interaction/SelectableNodeMovement.cs b/Editor/Gui/Graph/Interaction/SelectableNodeMovement.cs index c8002460ac..6b8f43aeca 100644 --- a/Editor/Gui/Graph/Interaction/SelectableNodeMovement.cs +++ b/Editor/Gui/Graph/Interaction/SelectableNodeMovement.cs @@ -12,6 +12,7 @@ using T3.Editor.Gui.Selection; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using Vector2 = System.Numerics.Vector2; namespace T3.Editor.Gui.Graph.Interaction diff --git a/Editor/Gui/Graph/Interaction/SymbolAnalysis.cs b/Editor/Gui/Graph/Interaction/SymbolAnalysis.cs index bc3006258e..b4185597f2 100644 --- a/Editor/Gui/Graph/Interaction/SymbolAnalysis.cs +++ b/Editor/Gui/Graph/Interaction/SymbolAnalysis.cs @@ -3,6 +3,7 @@ using System.Linq; using T3.Editor.Gui.Graph.Helpers; using T3.Editor.Gui.Graph.Modification; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { diff --git a/Editor/Gui/Graph/Interaction/SymbolBrowser.cs b/Editor/Gui/Graph/Interaction/SymbolBrowser.cs index 9f3a28ae76..d3ab792aca 100644 --- a/Editor/Gui/Graph/Interaction/SymbolBrowser.cs +++ b/Editor/Gui/Graph/Interaction/SymbolBrowser.cs @@ -12,10 +12,12 @@ using T3.Editor.Gui.Commands.Graph; using T3.Editor.Gui.Graph.Interaction.Connections; using T3.Editor.Gui.InputUi; +using T3.Editor.Gui.Interaction; using T3.Editor.Gui.Interaction.Variations; using T3.Editor.Gui.Interaction.Variations.Model; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { @@ -27,15 +29,44 @@ namespace T3.Editor.Gui.Graph.Interaction public class SymbolBrowser { #region public API ------------------------------------------------------------------------ - public void OpenAt(Vector2 positionOnCanvas, Type filterInputType, Type filterOutputType, bool onlyMultiInputs) + + public void OpenAt(Vector2 positionOnCanvas, Type filterInputType, Type filterOutputType, bool onlyMultiInputs, string startingSearchString = "", System.Action overrideCreate = null) { + // Scroll canvas to avoid symbol-browser close too edge + var primaryGraphWindow = GraphWindow.GetPrimaryGraphWindow(); + if (primaryGraphWindow?.GraphCanvas == null) + { + Log.Warning("Can't open symbol browser without graph window."); + return; + } + + var canvas = primaryGraphWindow.GraphCanvas; + if (canvas != null) + { + var screenPos = canvas.TransformPosition(positionOnCanvas); + var screenRect = ImRect.RectWithSize(screenPos, SymbolChildUi.DefaultOpSize); + screenRect.Expand(200 *canvas.Scale.X); + var windowRect = ImRect.RectWithSize(ImGui.GetWindowPos(), ImGui.GetWindowSize()); + var tooCloseToEdge = !windowRect.Contains(screenRect); + + var canvasPosition = canvas.InverseTransformPositionFloat(screenPos); + if (tooCloseToEdge) + { + var canvasRect = ImRect.RectWithSize(canvasPosition, SymbolChildUi.DefaultOpSize); + canvasRect.Expand(400); + canvas.FitAreaOnCanvas(canvasRect); + } + } + + //_prepareCommand = prepareCommand; + _overrideCreate = overrideCreate; IsOpen = true; PosOnCanvas = positionOnCanvas; _focusInputNextTime = true; _filter.FilterInputType = filterInputType; _filter.FilterOutputType = filterOutputType; - _filter.SearchString = ""; + _filter.SearchString = startingSearchString; _selectedSymbolUi = null; _filter.OnlyMultiInputs = onlyMultiInputs; _filter.UpdateIfNecessary(forceUpdate: true); @@ -60,7 +91,12 @@ public void Draw() if (NodeSelection.GetSelectedChildUis().Count() != 1) { ConnectionMaker.StartOperation("Add operator"); - OpenAt(GraphCanvas.Current.InverseTransformPositionFloat(ImGui.GetIO().MousePos + new Vector2(-4, -20)), null, null, false); + + var screenPos = ImGui.GetIO().MousePos + new Vector2(-4, -20); + var canvasPosition = GraphCanvas.Current.InverseTransformPositionFloat(screenPos); + + OpenAt(canvasPosition, null, null, false); + return; } @@ -73,6 +109,20 @@ public void Draw() return; } + var screenPos = GraphCanvas.Current.TransformPosition(childUi.PosOnCanvas); + var screenRect = ImRect.RectWithSize(screenPos, SymbolChildUi.DefaultOpSize); + screenRect.Expand(200 *GraphCanvas.Current.Scale.X); + var windowRect = ImRect.RectWithSize(ImGui.GetWindowPos(), ImGui.GetWindowSize()); + var tooCloseToEdge = !windowRect.Contains(screenRect); + + var canvasPosition = GraphCanvas.Current.InverseTransformPositionFloat(screenPos); + if (tooCloseToEdge) + { + var canvasRect = ImRect.RectWithSize(canvasPosition, SymbolChildUi.DefaultOpSize); + canvasRect.Expand(400); + GraphCanvas.Current.FitAreaOnCanvas(canvasRect); + } + ConnectionMaker.OpenBrowserWithSingleSelection(this, childUi, instance); } return; @@ -131,6 +181,8 @@ public void Draw() } #endregion + private System.Action _overrideCreate = null; + //private bool IsSearchingPresets => _filter.MatchingPresets.Count > 0; private void DrawSearchInput(Vector2 posInWindow, Vector2 posInScreen, Vector2 size) @@ -530,6 +582,13 @@ public static void DrawExampleOperator(Guid exampleId, string label) private void CreateInstance(Symbol symbol) { + if(_overrideCreate != null) + { + Close(); + _overrideCreate(symbol); + return; + } + var commandsForUndo = new List(); var parent = GraphCanvas.Current.CompositionOp.Symbol; diff --git a/Editor/Gui/Graph/Interaction/SymbolFilter.cs b/Editor/Gui/Graph/Interaction/SymbolFilter.cs index c5aabeecd2..1bcf7a18af 100644 --- a/Editor/Gui/Graph/Interaction/SymbolFilter.cs +++ b/Editor/Gui/Graph/Interaction/SymbolFilter.cs @@ -8,6 +8,7 @@ using T3.Editor.Gui.Graph.Interaction.Connections; using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.Interaction.Variations.Model; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Interaction { diff --git a/Editor/Gui/Graph/Modification/ChangeSymbol.cs b/Editor/Gui/Graph/Modification/ChangeSymbol.cs new file mode 100644 index 0000000000..a133ee22fc --- /dev/null +++ b/Editor/Gui/Graph/Modification/ChangeSymbol.cs @@ -0,0 +1,204 @@ + +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using Microsoft.CodeAnalysis; +using T3.Core.Logging; +using T3.Core.Operator; +using T3.Editor.Gui.Commands; +using T3.Editor.Gui.Selection; +using T3.Editor.Gui.Commands.Graph; +using T3.Editor.Gui.Graph.Interaction; +using T3.Editor.UiModel; + +namespace T3.Editor.Gui.Graph.Modification; + +internal static class ChangeSymbol +{ + public static void ChangeOperatorSymbol(Instance CompositionOp, List selectedChildUis, Symbol symbol) + { + var nextSelection = new List(); + + var executedCommands = new List(); + + foreach (var sel in selectedChildUis) + { + var result = ChangeSymbol.ChangeOperatorSymbol(sel, symbol, executedCommands); + if (result != null) + nextSelection.Add(result); + } + + if(nextSelection.Count > 0) + UndoRedoStack.Add(new MacroCommand(nextSelection.Count == 1 ? "Change Symbol" : "Change Symbols ("+ nextSelection.Count + ")", executedCommands)); + + NodeSelection.Clear(); + nextSelection.ForEach(symbolChild => { + var childUi = SymbolUiRegistry.Entries[symbolChild.Parent.Id].ChildUis.SingleOrDefault(ui => ui.SymbolChild == symbolChild); // need better map? + var instance = CompositionOp.Children.Single(c2 => c2.SymbolChildId == symbolChild.Id); + if (childUi != null && instance != null) + NodeSelection.AddSymbolChildToSelection(childUi, instance); + }); + } + + + public static SymbolChild ChangeOperatorSymbol(SymbolChildUi symbolChildUi, Symbol newSymbol, List executedCommands) + { + var symbolChild = symbolChildUi.SymbolChild; + if(symbolChild.Symbol == newSymbol) + return null; + + var orgPos = symbolChildUi.PosOnCanvas; + var parentSymbolUi = SymbolUiRegistry.Entries[symbolChild.Parent.Id]; + + var conversionWasLossy = false; + + // move old SymbolChild to new position + var moveCmd = new ModifyCanvasElementsCommand(parentSymbolUi, new List() { symbolChildUi }); + symbolChildUi.PosOnCanvas = orgPos + new Vector2(0, 100); + moveCmd.StoreCurrentValues(); + moveCmd.Do(); + executedCommands.Add(moveCmd); + + // create new SymbolChild at original position + var addSymbolChildCommand = new AddSymbolChildCommand(symbolChild.Parent, newSymbol.Id) { PosOnCanvas = orgPos, ChildName = symbolChild.Name }; + addSymbolChildCommand.Do(); + executedCommands.Add(addSymbolChildCommand); + + var newSymbolChild = symbolChild.Parent.Children.Single(entry => entry.Id == addSymbolChildCommand.AddedChildId); + + // loop though inputs + foreach (var input in symbolChild.Inputs) + { + var connections = symbolChild.Parent.Connections.FindAll(c => c.TargetSlotId == input.Key + && c.TargetParentOrChildId == symbolChild.Id); + + var inputName = input.Value.Name; + var destInput = newSymbolChild.Inputs.FirstOrDefault(x => x.Value.Name == inputName); + + if (connections.Count > 1) // can this happen? + { + Log.Warning("\"Change Symbol...\" : connections.Count > 1 : not yet implemented, skipping!"); + System.Diagnostics.Debug.Assert(false); + } + else + { + var inputHasData = connections.Count > 0 || !input.Value.IsDefault; + + if (destInput.Value != null) + { + if(input.Value.Value.ValueType == destInput.Value.Value.ValueType) + { + // treating default value as a special assignment, + // this is also how it is indicated in the UI. + // Just leave the initial value of newSymbol input + // (assuming this is same as default) + + if (!input.Value.IsDefault) + { + var changeValCommand = new ChangeInputValueCommand(symbolChild.Parent, newSymbolChild.Id, destInput.Value, input.Value.Value); + changeValCommand.Do(); + executedCommands.Add(changeValCommand); + } + + if (connections.Count == 1) + { + // remove old connection to symbolChild + + var delCommand = new DeleteConnectionCommand(symbolChild.Parent, connections[0], 0); + delCommand.Do(); + executedCommands.Add(delCommand); + + + // add new connection to newSymbolChild + + var newConnectionToInput = new Symbol.Connection( + sourceParentOrChildId: connections[0].SourceParentOrChildId, + sourceSlotId: connections[0].SourceSlotId, + targetParentOrChildId: newSymbolChild.Id, + targetSlotId: destInput.Key); + var addCommand = new AddConnectionCommand(symbolChild.Parent, newConnectionToInput, 0); + addCommand.Do(); + executedCommands.Add(addCommand); + } + } + else if(inputHasData) + { + conversionWasLossy = true; + Log.Info("\"Change Symbol...\" : type mismatching, input:" + inputName + ", " + input.Value.Value.ValueType + "(old) vs " + destInput.Value.Value.ValueType + "(new)"); + } + + } + else if(inputHasData) + { + conversionWasLossy = true; + Log.Info("\"Change Symbol...\" : no matching input, name: " + inputName); + } + + } + + } + + + // loop though outputs + foreach (var output in symbolChild.Outputs) + { + var connections = symbolChild.Parent.Connections.FindAll(c => c.SourceSlotId == output.Key + && c.SourceParentOrChildId == symbolChild.Id); + + var outputName = output.Value.OutputDefinition.Name; + var destOutput = newSymbolChild.Outputs.FirstOrDefault(x => x.Value.OutputDefinition.Name == outputName); + + foreach (var connection in connections) + { + if (destOutput.Value != null) + { + if (output.Value.OutputDefinition.ValueType == destOutput.Value.OutputDefinition.ValueType) + { + // remove old connection from symbolChild + + var multiInputIndex = symbolChild.Parent.GetMultiInputIndexFor(connection); + var delCommand = new DeleteConnectionCommand(symbolChild.Parent, connection, multiInputIndex); + delCommand.Do(); + executedCommands.Add(delCommand); + + + + // add new connection from newSymbolChild + + var newConnectionToInput = new Symbol.Connection( + sourceParentOrChildId: newSymbolChild.Id, + sourceSlotId: destOutput.Key, + targetParentOrChildId: connection.TargetParentOrChildId, + targetSlotId: connection.TargetSlotId); + var addCommand = new AddConnectionCommand(symbolChild.Parent, newConnectionToInput, multiInputIndex); + addCommand.Do(); + executedCommands.Add(addCommand); + } + else + { + conversionWasLossy = true; + Log.Info("\"Change Symbol...\" : type mismatching, input:" + outputName + ", " + output.Value.OutputDefinition.ValueType + "(old) vs " + destOutput.Value.OutputDefinition.ValueType + "(new)"); + } + } + else + { + conversionWasLossy = true; + Log.Info("\"Change Symbol...\" : no matching output, name: " + outputName + " (connection left as is)"); + } + } + } + + if(!conversionWasLossy) + { + var delCommand = new DeleteSymbolChildrenCommand(parentSymbolUi, new List() { symbolChildUi }); + delCommand.Do(); + executedCommands.Add(delCommand); + } + else + { + Log.Warning("\"Change Symbol...\" : old operator not deleted due to lossy conversion"); + } + + return newSymbolChild; + } +} \ No newline at end of file diff --git a/Editor/Gui/Graph/Modification/Combine.cs b/Editor/Gui/Graph/Modification/Combine.cs index 3881c193c5..dbdd0c9c7b 100644 --- a/Editor/Gui/Graph/Modification/Combine.cs +++ b/Editor/Gui/Graph/Modification/Combine.cs @@ -12,6 +12,7 @@ using T3.Editor.Gui.Commands.Annotations; using T3.Editor.Gui.Commands.Graph; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Modification; diff --git a/Editor/Gui/Graph/Modification/Duplicate.cs b/Editor/Gui/Graph/Modification/Duplicate.cs index 887870cdd3..0661d9f940 100644 --- a/Editor/Gui/Graph/Modification/Duplicate.cs +++ b/Editor/Gui/Graph/Modification/Duplicate.cs @@ -13,6 +13,7 @@ using T3.Editor.Gui.Commands; using T3.Editor.Gui.Commands.Graph; using T3.Editor.Gui.Graph.Helpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Modification; diff --git a/Editor/Gui/Graph/Modification/InputsAndOutputs.cs b/Editor/Gui/Graph/Modification/InputsAndOutputs.cs index df34735ae1..7c2e3078eb 100644 --- a/Editor/Gui/Graph/Modification/InputsAndOutputs.cs +++ b/Editor/Gui/Graph/Modification/InputsAndOutputs.cs @@ -10,6 +10,7 @@ using T3.Core.Operator; using T3.Core.Resource; using T3.Editor.Gui.Graph.Helpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph.Modification; diff --git a/Editor/Gui/Graph/OutputNode.cs b/Editor/Gui/Graph/OutputNode.cs index 86cf568818..59bd4562a5 100644 --- a/Editor/Gui/Graph/OutputNode.cs +++ b/Editor/Gui/Graph/OutputNode.cs @@ -51,12 +51,12 @@ public static void Draw(Symbol.OutputDefinition outputDef, IOutputUi outputUi) // ColorVariations.OperatorInputZone.Apply(typeColor)); // Label - { + if(!string.IsNullOrEmpty(outputDef.Name)){ var isScaledDown = GraphCanvas.Current.Scale.X < 1; drawList.PushClipRect(LastScreenRect.Min, LastScreenRect.Max, true); ImGui.PushFont(isScaledDown ? Fonts.FontSmall : Fonts.FontBold); - var label = string.Format($"{outputDef.Name}"); + var label = outputDef.Name; drawList.AddText(LastScreenRect.Min, ColorVariations.OperatorLabel.Apply(typeColor), label); ImGui.PopFont(); diff --git a/Editor/Gui/Graph/ParameterPopUp.cs b/Editor/Gui/Graph/ParameterPopUp.cs index dbbf6c097a..d9639e220f 100644 --- a/Editor/Gui/Graph/ParameterPopUp.cs +++ b/Editor/Gui/Graph/ParameterPopUp.cs @@ -12,6 +12,7 @@ using T3.Editor.Gui.Windows; using T3.Editor.Gui.Windows.Layouts; using T3.Editor.Gui.Windows.Variations; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph; @@ -78,14 +79,20 @@ public static void DrawParameterPopUp(GraphWindow graphWindow) ImGui.SetNextWindowPos(screenPos); var preventTabbingIntoUnfocusedStringInputs = ImGui.IsAnyItemActive() ? ImGuiWindowFlags.None : ImGuiWindowFlags.NoNavInputs; - if (ImGui.BeginChild("Popup", new Vector2(280, height), true, preventTabbingIntoUnfocusedStringInputs)) + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); + if (ImGui.BeginChild("Popup", + new Vector2(280, height), + true, + preventTabbingIntoUnfocusedStringInputs + | ImGuiWindowFlags.NoScrollbar)) { if (ImGui.IsKeyDown(ImGuiKey.Escape)) { Close(); } - ImGui.GetWindowDrawList().AddRectFilled(ImGui.GetWindowPos(), - ImGui.GetWindowPos() + ImGui.GetWindowSize(), + + ImGui.GetWindowDrawList().AddRectFilled(ImGui.GetWindowPos(), + ImGui.GetWindowPos() + ImGui.GetWindowSize(), UiColors.BackgroundFull); FormInputs.SetIndent(20); @@ -95,21 +102,28 @@ public static void DrawParameterPopUp(GraphWindow graphWindow) ImGui.SetWindowFocus(); _focusDelayCount--; } - else if (!ImGui.IsWindowFocused(ImGuiFocusedFlags.ChildWindows)) { Close(); } - CustomComponents.AddSegmentedIconButton(ref _viewMode, _modeIcons); - ImGui.SameLine(0, 20); - var isPinned = _selectedInstance == graphWindow.GraphImageBackground.OutputInstance; - if (CustomComponents.DrawIconToggle("enabled", Icon.PlayOutput, ref isPinned)) + // Toolbar { - if (isPinned) - graphWindow.SetBackgroundOutput(_selectedInstance); + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(4,4) * T3Ui.UiScaleFactor); + ImGui.SetCursorPos( new Vector2(5,5)); + CustomComponents.AddSegmentedIconButton(ref _viewMode, _modeIcons); + ImGui.SameLine(0, 20); + + var isPinned = _selectedInstance == graphWindow.GraphImageBackground.OutputInstance; + if (CustomComponents.DrawIconToggle("enabled", Icon.PlayOutput, ref isPinned)) + { + if (isPinned) + graphWindow.SetBackgroundOutput(_selectedInstance); + } + ImGui.PopStyleVar(); } + // Content switch (_viewMode) { case ViewModes.Parameters: @@ -145,10 +159,10 @@ public static void DrawParameterPopUp(GraphWindow graphWindow) } _lastRequiredHeight = ImGui.GetCursorPosY(); - } ImGui.EndChild(); + ImGui.PopStyleVar(); } private static void Close() @@ -176,7 +190,7 @@ private enum ViewModes private static bool _isOpen; private static int _focusDelayCount; - + private static GraphCanvas _graphCanvas; private static ViewModes _viewMode = ViewModes.Parameters; private static Instance _selectedInstance; diff --git a/Editor/Gui/Graph/PlayerExporter.cs b/Editor/Gui/Graph/PlayerExporter.cs index e5e552e2bc..90d4a21b10 100644 --- a/Editor/Gui/Graph/PlayerExporter.cs +++ b/Editor/Gui/Graph/PlayerExporter.cs @@ -16,6 +16,7 @@ using T3.Editor.Gui.Audio; using T3.Editor.Gui.InputUi.SimpleInputUis; using T3.Editor.Gui.Interaction.Timing; +using T3.Editor.UiModel; // ReSharper disable StringLiteralTypo diff --git a/Editor/Gui/Graph/RenameInstanceOverlay.cs b/Editor/Gui/Graph/RenameInstanceOverlay.cs index 36c6717459..c5a018ad32 100644 --- a/Editor/Gui/Graph/RenameInstanceOverlay.cs +++ b/Editor/Gui/Graph/RenameInstanceOverlay.cs @@ -1,9 +1,12 @@ using System; using System.Linq; +using System.Numerics; using ImGuiNET; using T3.Core.IO; using T3.Core.Logging; using T3.Editor.Gui.Graph.Interaction; +using T3.Editor.Gui.Styling; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Graph { @@ -67,11 +70,12 @@ public static void Draw() var positionInScreen = GraphCanvas.Current.TransformPosition(symbolChildUi.PosOnCanvas); - ImGui.SetCursorScreenPos(positionInScreen); + ImGui.SetCursorScreenPos(positionInScreen + Vector2.One); var text = symbolChild.Name; - ImGui.SetNextItemWidth(150); - ImGui.InputText("##input", ref text, 256, ImGuiInputTextFlags.AutoSelectAll); + //ImGui.SetNextItemWidth(160); + CustomComponents.DrawInputFieldWithPlaceholder("Untitled", ref text, 200, false, ImGuiInputTextFlags.AutoSelectAll); + //ImGui.InputText("##input", ref text, 256, ImGuiInputTextFlags.AutoSelectAll); symbolChild.Name = text; if (!justOpened && (ImGui.IsItemDeactivated() || ImGui.IsKeyPressed((ImGuiKey)Key.Return))) diff --git a/Editor/Gui/InputUi/CombinedInputs/CurveInputEditing.cs b/Editor/Gui/InputUi/CombinedInputs/CurveInputEditing.cs index f0af981d6a..1c784ce839 100644 --- a/Editor/Gui/InputUi/CombinedInputs/CurveInputEditing.cs +++ b/Editor/Gui/InputUi/CombinedInputs/CurveInputEditing.cs @@ -61,7 +61,6 @@ public static InputEditStateFlags DrawCanvasForCurve(ref Curve curveRef, SymbolC curveInteraction.Curves.Add(curveForEditing); } - curveInteraction.EditState = InputEditStateFlags.Nothing; curveInteraction.Draw(); @@ -72,6 +71,8 @@ public static InputEditStateFlags DrawCanvasForCurve(ref Curve curveRef, SymbolC curveRef = curveForEditing; _clonedDefaultCurves.Remove(input.DefaultValue); } + + return curveInteraction.EditState; } @@ -85,10 +86,10 @@ public static ScalableCanvas GetCanvasForCurve(Curve curve) /// /// Implement interaction of manipulating the individual keyframes /// - private class CurveInteraction : CurveEditing + public class CurveInteraction : CurveEditing { - public List Curves = new List(); - private readonly SingleCurveEditCanvas _singleCurveCanvas = new SingleCurveEditCanvas() { ImGuiTitle = "canvas" + _interactionForCurve.Count }; + public List Curves = new(); + private readonly SingleCurveEditCanvas _singleCurveCanvas = new() { ImGuiTitle = "canvas" + _interactionForCurve.Count }; //public ScalableCanvas Canvas => _canvas; @@ -99,6 +100,7 @@ public void Draw() _singleCurveCanvas.Draw(Curves[0], this); } + #region implement editing --------------------------------------------------------------- protected override IEnumerable GetAllCurves() { @@ -147,7 +149,8 @@ protected internal override void HandleCurvePointDragging(VDefinition vDef, bool } else { - Log.Error("Deactivated keyframe dragging without valid command?"); + // This happens when clicking on keyframes for selection... + //Log.Error("Deactivated keyframe dragging without valid command?"); } } @@ -259,7 +262,7 @@ private void HandleFenceSelection() /// /// Implement canvas for showing and manipulating curve /// - private class SingleCurveEditCanvas : CurveEditCanvas + internal class SingleCurveEditCanvas : CurveEditCanvas { public SingleCurveEditCanvas() { @@ -269,7 +272,7 @@ public SingleCurveEditCanvas() public void Draw(Curve curve, CurveInteraction interaction) { - var height = (_interactionFlags & T3Ui.EditingFlags.ExpandVertically) == T3Ui.EditingFlags.ExpandVertically + var height = _interactionFlags.HasFlag(T3Ui.EditingFlags.ExpandVertically) ? ImGui.GetContentRegionAvail().Y : DefaultCurveParameterHeight; @@ -322,7 +325,7 @@ void DrawCanvasContent() if (NeedToAdjustScopeAfterFirstRendering) { var bounds = GetBoundsOnCanvas(interaction.GetAllKeyframes()); - SetScopeToCanvasArea(bounds, flipY: true, GraphCanvas.Current, 100, 100); + SetScopeToCanvasArea(bounds, flipY: true, GraphCanvas.Current, 30, 15); NeedToAdjustScopeAfterFirstRendering = false; } } diff --git a/Editor/Gui/InputUi/CombinedInputs/CurveInputUi.cs b/Editor/Gui/InputUi/CombinedInputs/CurveInputUi.cs index 86e5ecfbea..1180835433 100644 --- a/Editor/Gui/InputUi/CombinedInputs/CurveInputUi.cs +++ b/Editor/Gui/InputUi/CombinedInputs/CurveInputUi.cs @@ -2,6 +2,8 @@ using ImGuiNET; using T3.Core.DataTypes; using T3.Core.Operator; +using T3.Editor.Gui.Interaction; +using T3.Editor.Gui.Styling; namespace T3.Editor.Gui.InputUi.CombinedInputs { @@ -30,8 +32,16 @@ protected override InputEditStateFlags DrawEditControl(string name, SymbolChild. ImGui.Dummy(Vector2.One); // Add Line Break + var keepPositionForIcon = ImGui.GetCursorPos(); + var cloneIfModified = input.IsDefault; var modified= CurveInputEditing.DrawCanvasForCurve(ref curve, input, cloneIfModified, T3Ui.EditingFlags.PreventZoomWithMouseWheel); + + if (CurveEditPopup.DrawPopupIndicator(input, ref curve, keepPositionForIcon, cloneIfModified, out var popupResult)) + { + modified = popupResult; + } + if (cloneIfModified && (modified & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing) { input.IsDefault = false; diff --git a/Editor/Gui/InputUi/IInputUi.cs b/Editor/Gui/InputUi/IInputUi.cs index ba7f38cfd5..f19f55a8b5 100644 --- a/Editor/Gui/InputUi/IInputUi.cs +++ b/Editor/Gui/InputUi/IInputUi.cs @@ -4,6 +4,7 @@ using T3.Core.Operator; using T3.Core.Operator.Slots; using T3.Editor.Gui.Selection; +using T3.Editor.UiModel; namespace T3.Editor.Gui.InputUi { diff --git a/Editor/Gui/InputUi/InputValueUi.cs b/Editor/Gui/InputUi/InputValueUi.cs index b4ecde8b47..62e26f41e2 100644 --- a/Editor/Gui/InputUi/InputValueUi.cs +++ b/Editor/Gui/InputUi/InputValueUi.cs @@ -26,6 +26,7 @@ using T3.Editor.Gui.Selection; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.InputUi { @@ -283,7 +284,7 @@ InputEditStateFlags DrawAnimatedParameter() // Draw Name ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(1.0f, 0.5f)); - ImGui.Button(input.Name + "##ParamName", new Vector2(ParameterNameWidth, 0.0f)); + var isClicked = ImGui.Button(input.Name + "##ParamName", new Vector2(ParameterNameWidth, 0.0f)); CustomComponents.ContextMenuForItem(() => { if (ImGui.MenuItem("Jump To Previous Keyframe", hasKeyframeBefore)) @@ -324,6 +325,20 @@ InputEditStateFlags DrawAnimatedParameter() editState = InputEditStateFlags.ShowOptions; }); ImGui.PopStyleVar(); + + if(ImGui.IsItemHovered()) + Icons.DrawIconAtScreenPosition(Icon.Revert, ImGui.GetItemRectMin() + new Vector2(6, 4) * T3Ui.UiScaleFactor); + + if (isClicked) + { + var commands = new List(); + commands.Add(new RemoveAnimationsCommand(animator, new[] { inputSlot })); + commands.Add(new ResetInputToDefault(compositionSymbol, symbolChildUi.Id, input)); + var marcoCommand = new MacroCommand("Reset animated " + input.Name, commands ); + UndoRedoStack.AddAndExecute(marcoCommand); + } + + ImGui.SameLine(); ImGui.PushItemWidth(200.0f); @@ -448,13 +463,12 @@ InputEditStateFlags DrawNormalParameter() { var isClicked = ImGui.Button(input.Name + "##ParamName", new Vector2(ParameterNameWidth, 0.0f)); ImGui.SameLine(); - if (!input.IsDefault) + if(ImGui.IsItemHovered()) + Icons.DrawIconAtScreenPosition(Icon.Revert, ImGui.GetItemRectMin() + new Vector2(6, 4)); + + if (isClicked) { - Icons.DrawIconAtScreenPosition(Icon.Revert, ImGui.GetItemRectMin() + new Vector2(6, 2)); - if (isClicked) - { - UndoRedoStack.AddAndExecute(new ResetInputToDefault(compositionSymbol, symbolChildUi.Id, input)); - } + UndoRedoStack.AddAndExecute(new ResetInputToDefault(compositionSymbol, symbolChildUi.Id, input)); } } diff --git a/Editor/Gui/InputUi/SimpleInputUis/StringInputUi.cs b/Editor/Gui/InputUi/SimpleInputUis/StringInputUi.cs index cd9f0f29b4..0cbe1539ac 100644 --- a/Editor/Gui/InputUi/SimpleInputUis/StringInputUi.cs +++ b/Editor/Gui/InputUi/SimpleInputUis/StringInputUi.cs @@ -4,8 +4,11 @@ using ImGuiNET; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using T3.Core.Logging; using T3.Core.Operator; +using T3.Core.Operator.Interfaces; using T3.Core.Resource; +using T3.Editor.Gui.Graph.Interaction; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; @@ -21,6 +24,7 @@ public enum UsageType FilePath, DirectoryPath, Multiline, + CustomDropdown, } public UsageType Usage { get; private set; } = UsageType.Default; @@ -64,6 +68,9 @@ protected override InputEditStateFlags DrawEditControl(string name, SymbolChild. case UsageType.DirectoryPath: inputEditStateFlags = DrawEditWithSelectors(FileOperations.FilePickerTypes.Folder, ref value); break; + case UsageType.CustomDropdown: + inputEditStateFlags = DrawCustomDropdown(input, ref value); + break; } inputEditStateFlags |= ImGui.IsItemClicked() ? InputEditStateFlags.Started : InputEditStateFlags.Nothing; @@ -85,10 +92,10 @@ private static InputEditStateFlags DrawEditWithSelectors(FileOperations.FilePick if (warning != string.Empty) ImGui.PushStyleColor(ImGuiCol.Text, UiColors.StatusAnimated.Rgba); - + var inputEditStateFlags = DrawDefaultTextEdit(ref value); - - if(warning !=string.Empty) + + if (warning != string.Empty) ImGui.PopStyleColor(); if (ImGui.IsItemHovered() && ImGui.CalcTextSize(value).X > ImGui.GetItemRectSize().X) @@ -121,6 +128,42 @@ private static InputEditStateFlags DrawMultilineTextEdit(ref string value) return changed ? InputEditStateFlags.Modified : InputEditStateFlags.Nothing; } + private static InputEditStateFlags DrawCustomDropdown(SymbolChild.Input input, ref string value) + { + var instance = NodeSelection.GetSelectedInstance(); + if (instance is ICustomDropdownHolder customValueHoder) + { + var changed = false; + + var currentValue = customValueHoder.GetValueForInput(input.InputDefinition.Id); + if (ImGui.BeginCombo("##customDropdown", currentValue, ImGuiComboFlags.HeightLarge)) + { + foreach (var value2 in customValueHoder.GetOptionsForInput(input.InputDefinition.Id)) + { + if (value2 == null) + continue; + + var isSelected = value2 == currentValue; + if (!ImGui.Selectable($"{value2}", isSelected, ImGuiSelectableFlags.DontClosePopups)) + continue; + + ImGui.CloseCurrentPopup(); + customValueHoder.HandleResultForInput(input.InputDefinition.Id, value2); + changed = true; + } + + ImGui.EndCombo(); + } + + return changed ? InputEditStateFlags.Modified : InputEditStateFlags.Nothing; + } + else + { + Log.Warning($"{instance} doesn't support custom inputs"); + return InputEditStateFlags.Nothing; + } + } + protected override void DrawReadOnlyControl(string name, ref string value) { if (value != null) @@ -143,10 +186,9 @@ public override void DrawSettings() var tmpForRef = Usage; if (FormInputs.AddEnumDropdown(ref tmpForRef, "Usage")) Usage = tmpForRef; - } - - if (Usage == UsageType.FilePath) + + if (Usage == UsageType.FilePath) { var tmp = FileFilter; var warning = !string.IsNullOrEmpty(tmp) && !tmp.Contains('|') @@ -166,8 +208,8 @@ public override void Write(JsonTextWriter writer) base.Write(writer); writer.WriteObject(nameof(Usage), Usage.ToString()); - - if(!string.IsNullOrEmpty(FileFilter)) + + if (!string.IsNullOrEmpty(FileFilter)) writer.WriteObject(nameof(FileFilter), FileFilter); } @@ -175,7 +217,7 @@ public override void Read(JToken inputToken) { if (inputToken == null) return; - + base.Read(inputToken); if (Enum.TryParse(inputToken[nameof(Usage)].Value(), out var enumValue)) diff --git a/Editor/Gui/InputUi/VectorInputs/IntInputUi.cs b/Editor/Gui/InputUi/VectorInputs/IntInputUi.cs index c747067857..57413a7ce1 100644 --- a/Editor/Gui/InputUi/VectorInputs/IntInputUi.cs +++ b/Editor/Gui/InputUi/VectorInputs/IntInputUi.cs @@ -5,7 +5,9 @@ using T3.Core.DataTypes; using T3.Core.Operator; using T3.Core.Operator.Slots; +using T3.Core.Utils; using T3.Editor.Gui.Interaction; +using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; namespace T3.Editor.Gui.InputUi.VectorInputs @@ -120,7 +122,27 @@ public static InputEditStateFlags DrawEnumInputEdit(ref int value, Type enumType editStateFlags |= InputEditStateFlags.ModifiedAndFinished; } - if (ImGui.IsItemClicked()) + if (!ImGui.IsItemActive()) + { + var io = ImGui.GetIO(); + if (ImGui.IsItemHovered() && io.KeyCtrl) + { + T3Ui.MouseWheelFieldHovered = true; + ImGui.SetMouseCursor(ImGuiMouseCursor.ResizeEW); + var dl = ImGui.GetForegroundDrawList(); + dl.AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), UiColors.StatusActivated); + + var wheel = io.MouseWheel; + if (wheel == 0) + return InputEditStateFlags.Nothing; + + var delta = wheel > 0 ? -1 : 1; + value= (value + delta).Clamp(0, enumInfo.ValueNames.Length-1); + + return InputEditStateFlags.Modified; + } + } + else if (ImGui.IsItemClicked()) { editStateFlags |= InputEditStateFlags.Started; } diff --git a/Editor/Gui/Interaction/Camera/CameraInteraction.cs b/Editor/Gui/Interaction/Camera/CameraInteraction.cs index eb9c968e65..40f1ed01e1 100644 --- a/Editor/Gui/Interaction/Camera/CameraInteraction.cs +++ b/Editor/Gui/Interaction/Camera/CameraInteraction.cs @@ -302,25 +302,25 @@ private void ManipulateCameraByKeyboard() var acc = CameraInteractionParameters.CameraAcceleration * UserSettings.Config.CameraSpeed * _deltaTime * 60; - if (ImGui.IsKeyDown((ImGuiKey)Key.A) || ImGui.IsKeyDown((ImGuiKey)Key.CursorLeft)) + if (ImGui.IsKeyDown((ImGuiKey)Key.A)) { _moveVelocity += _viewAxis.Left * acc; _manipulatedByKeyboard = true; } - if (ImGui.IsKeyDown((ImGuiKey)Key.D) || ImGui.IsKeyDown((ImGuiKey)Key.CursorRight)) + if (ImGui.IsKeyDown((ImGuiKey)Key.D)) { _moveVelocity -= _viewAxis.Left * acc; _manipulatedByKeyboard = true; } - if (ImGui.IsKeyDown((ImGuiKey)Key.W) || ImGui.IsKeyDown((ImGuiKey)Key.CursorUp)) + if (ImGui.IsKeyDown((ImGuiKey)Key.W)) { _moveVelocity += Vector3.Normalize(_viewAxis.ViewDistance) * acc; _manipulatedByKeyboard = true; } - if (ImGui.IsKeyDown((ImGuiKey)Key.S) || ImGui.IsKeyDown((ImGuiKey)Key.CursorDown)) + if (ImGui.IsKeyDown((ImGuiKey)Key.S)) { _moveVelocity -= Vector3.Normalize(_viewAxis.ViewDistance) * acc; _manipulatedByKeyboard = true; diff --git a/Editor/Gui/Interaction/ColorEditButton.cs b/Editor/Gui/Interaction/ColorEditButton.cs index 58f5dd599a..e6451f26ed 100644 --- a/Editor/Gui/Interaction/ColorEditButton.cs +++ b/Editor/Gui/Interaction/ColorEditButton.cs @@ -21,9 +21,10 @@ public static InputEditStateFlags Draw(ref Vector4 color, Vector2 size, bool tri if (triggerOpen || ImGui.IsItemHovered( ImGuiHoveredFlags.AllowWhenBlockedByPopup) && ImGui.IsMouseReleased(0) && ImGui.GetIO().MouseDragMaxDistanceAbs[0].Length() < UserSettings.Config.ClickThreshold - && !ImGui.IsPopupOpen("##colorEdit") + && !ImGui.IsPopupOpen(ColorEditPopup.PopupId) ) { + _previousColor = color; _modifiedSlider = false; ImGui.OpenPopup("##colorEdit"); ImGui.SetNextWindowPos(ImGui.GetItemRectMax() + new Vector2(4,10)); @@ -31,8 +32,6 @@ public static InputEditStateFlags Draw(ref Vector4 color, Vector2 size, bool tri edited |= HandleQuickSliders(ref color, buttonPosition); edited |= ColorEditPopup.DrawPopup(ref color, _previousColor); - if (edited == InputEditStateFlags.ModifiedAndFinished) - _previousColor = color; return edited; } diff --git a/Editor/Gui/Interaction/ColorEditPopup.cs b/Editor/Gui/Interaction/ColorEditPopup.cs index ea3323f3ed..ce29c232f4 100644 --- a/Editor/Gui/Interaction/ColorEditPopup.cs +++ b/Editor/Gui/Interaction/ColorEditPopup.cs @@ -16,6 +16,7 @@ using T3.Editor.Gui.Selection; using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; using Color = T3.Editor.Gui.Styling.Color; using Point = System.Drawing.Point; @@ -28,10 +29,11 @@ public static InputEditStateFlags DrawPopup(ref Vector4 color, Vector4 previousC var edited = InputEditStateFlags.Nothing; var cColor = new Color(color); ImGui.SetNextWindowSize(new Vector2(257, 360)); + ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); var dontCloseIfColorPicking = ImGui.GetIO().KeyAlt ? ImGuiWindowFlags.Modal : ImGuiWindowFlags.None; var id = ImGui.GetID("colorPicker"); - if (ImGui.BeginPopup("##colorEdit", dontCloseIfColorPicking)) + if (ImGui.BeginPopup(PopupId, dontCloseIfColorPicking)) { if (_openedId != id) { @@ -63,6 +65,7 @@ public static InputEditStateFlags DrawPopup(ref Vector4 color, Vector4 previousC } color = cColor.Rgba; + ImGui.PopStyleVar(); return edited; } @@ -70,40 +73,38 @@ private static InputEditStateFlags PickColor(ref Color cColor, Vector4 previousC { InputEditStateFlags edited = InputEditStateFlags.Nothing; + Color pickedColor; // Pick colors var altKeyPressed = ImGui.GetIO().KeyAlt; - if (altKeyPressed) + if (!altKeyPressed) + return edited; + + pickedColor = GetColorAtMousePosition(); + if (ImGui.IsMouseClicked(ImGuiMouseButton.Left)) { - cColor = GetColorAtMousePosition(); - if (ImGui.IsMouseClicked(ImGuiMouseButton.Left)) - { - edited |= InputEditStateFlags.ModifiedAndFinished; - } - - var dl = ImGui.GetForegroundDrawList(); - var pos = ImGui.GetMousePos(); - - pos += Vector2.One * 25; - dl.AddRectFilled(pos, pos + new Vector2(40, 38), UiColors.BackgroundFull); - ImGui.PushFont(Fonts.FontSmall); - dl.AddText(pos + new Vector2(5, 2 + 0), UiColors.ForegroundFull, $"{cColor.R:0.000}"); - dl.AddText(pos + new Vector2(5, 2 + 10), UiColors.ForegroundFull, $"{cColor.G:0.000}"); - dl.AddText(pos + new Vector2(5, 2 + 20), UiColors.ForegroundFull, $"{cColor.B:0.000}"); - ImGui.PopFont(); + edited |= InputEditStateFlags.ModifiedAndFinished; + cColor = pickedColor; } - if (ImGui.IsKeyReleased(ImGuiKey.ModAlt)) - { - if (!Program.IsCursorInsideAppWindow) - { - edited |= InputEditStateFlags.ModifiedAndFinished; - } - else - { - cColor.Rgba = previousColor; - edited = InputEditStateFlags.Nothing; - } - } + var dl = ImGui.GetForegroundDrawList(); + var pos = ImGui.GetMousePos(); + + pos += Vector2.One * 25; + var padding = new Vector2(5, 5); + dl.AddRectFilled(pos, pos + new Vector2(80, 38), UiColors.BackgroundFull); + ImGui.PushFont(Fonts.FontSmall); + dl.AddText(pos + new Vector2(15, 2 + 0), UiColors.ForegroundFull, $"{pickedColor.R:0.000}"); + dl.AddText(pos + new Vector2(15, 2 + 10), UiColors.ForegroundFull, $"{pickedColor.G:0.000}"); + dl.AddText(pos + new Vector2(15, 2 + 20), UiColors.ForegroundFull, $"{pickedColor.B:0.000}"); + + dl.AddText(pos + new Vector2(55, 2 + 0), UiColors.ForegroundFull, $"{(pickedColor.R * 255):0}"); + dl.AddText(pos + new Vector2(55, 2 + 10), UiColors.ForegroundFull, $"{(pickedColor.G * 255):0}"); + dl.AddText(pos + new Vector2(55, 2 + 20), UiColors.ForegroundFull, $"{(pickedColor.B * 255):0}"); + + var swatchSize = new Vector2(3, 32); + var swatchPos = pos + new Vector2(3, 3); + dl.AddRectFilled(swatchPos, swatchPos+ swatchSize, pickedColor ); + ImGui.PopFont(); return edited; } @@ -193,12 +194,39 @@ private static InputEditStateFlags DrawCircleAndSliders(ref Color cColor, Vector var pMin = windowPos + new Vector2(size.X + 10, 0); var visibleBarSize = new Vector2(barWidth, barHeight); var pMax = pMin + visibleBarSize; - drawList.AddRectFilled(pMin - Vector2.One, pMax + Vector2.One, Color.Black); + + var hrdEditEnabled = ImGui.GetIO().KeyCtrl; + if (hrdEditEnabled) + { + var hdrOffset = new Vector2(0, -300); + drawList.AddRectFilled(pMin - Vector2.One + hdrOffset, pMax + Vector2.One, Color.Black); + } + else + { + drawList.AddRectFilled(pMin - Vector2.One, pMax + Vector2.One, Color.Black); + if (cColor.V > 1) + { + var offset = new Vector2(4,-5); + drawList.AddTriangleFilled( + pMin + new Vector2(-6,0) + offset, + pMin + new Vector2(0,-10) + offset, + pMin + new Vector2(6,0) + offset, + UiColors.ForegroundFull + ); + } + } + + if (cColor.V > 1) + { + var label = $"× {cColor.V:0.00}"; + var labelWidth = ImGui.CalcTextSize(label); + drawList.AddText(pMin - new Vector2(labelWidth.X+10, +20), UiColors.Text, label); + } var brightColor = cColor; brightColor.V = 1; brightColor.A = 1; - + drawList.AddRectFilledMultiColor(pMin, pMax, ImGui.ColorConvertFloat4ToU32(brightColor), ImGui.ColorConvertFloat4ToU32(brightColor), @@ -206,14 +234,19 @@ private static InputEditStateFlags DrawCircleAndSliders(ref Color cColor, Vector ImGui.ColorConvertFloat4ToU32(transparentColor)); // Draw compare value + if(compareValue <= 1 || hrdEditEnabled) { - var handlePos = new Vector2(0, barHeight * (1 - compareValue)) + pMin; + var mappedHdrValue = GetYFromHdr(compareValue); + var handlePos = new Vector2(0, barHeight * (1 - mappedHdrValue)) + pMin; drawList.AddRectFilled(handlePos, handlePos + new Vector2(barWidth + 2, 2), UiColors.ForegroundFull.Fade(0.5f)); } // Draw indicator + if(cColor.V <= 1 || hrdEditEnabled) { - var handlePos = new Vector2(0, barHeight * (1 - cColor.V)) + pMin; + var mappedHdrValue = GetYFromHdr(cColor.V); + + var handlePos = new Vector2(0, barHeight * (1 - mappedHdrValue)) + pMin; drawList.AddRectFilled(handlePos - Vector2.One, handlePos + new Vector2(barWidth + 2, 3), UiColors.BackgroundFull); drawList.AddRectFilled(handlePos, handlePos + new Vector2(barWidth + 2, 2), UiColors.ForegroundFull); } @@ -221,12 +254,13 @@ private static InputEditStateFlags DrawCircleAndSliders(ref Color cColor, Vector ImGui.InvisibleButton("intensitySlider", new Vector2(visibleBarSize.X * 4, visibleBarSize.Y)); if (ImGui.IsItemActive()) { - var clampUpperValue = ImGui.GetIO().KeyCtrl ? 100 : 1; + var clampUpperValue = hrdEditEnabled ? 100 : 1; var normalizedValue = (1 - (ImGui.GetMousePos() - pMin).Y / barHeight).Clamp(0, clampUpperValue); - if (normalizedValue > 1) - { - normalizedValue = MathF.Pow(normalizedValue, 3); - } + normalizedValue = GetHdrYValue(normalizedValue); + // if (normalizedValue > 1) + // { + // normalizedValue = MathF.Pow(normalizedValue, 3); + // } cColor.V = normalizedValue; @@ -301,6 +335,16 @@ private static InputEditStateFlags DrawCircleAndSliders(ref Color cColor, Vector return edited; } + private static float GetYFromHdr(float value) + { + return value < 1 ? value : MathF.Pow((value).Clamp(0,1000), 1/3f); + } + + private static float GetHdrYValue(float value) + { + return value < 1 ? value : MathF.Pow((value).Clamp(0,1000), 3f); + } + private enum ColorInputModes { Hsl, @@ -328,6 +372,7 @@ private static InputEditStateFlags DrawColorInputs(ref Color cColor, float hNorm { _inputMode = (ColorInputModes)((int)(_inputMode + 1) % Enum.GetNames(typeof(ColorInputModes)).Length); } + CustomComponents.TooltipForLastItem("Click to toggle between HSL, RGBA, integers and Hex input"); ImGui.PopStyleColor(); } @@ -596,7 +641,7 @@ private static InputEditStateFlags DrawUsedColors(ref Color cColor) var min = ImGui.GetItemRectMin(); var max = ImGui.GetItemRectMax() - Vector2.One; - wdl.AddText(Icons.IconFont, 14, min, new Color(0.1f), "" + (char)T3.Editor.Gui.Styling.Icon.Stripe4PxPattern); + wdl.AddText(Icons.IconFont, 13, min, new Color(0.1f), "" + (char)T3.Editor.Gui.Styling.Icon.Stripe4PxPattern); var opaqueColor = new Color( usedColor.X, @@ -670,7 +715,7 @@ private static void SelectRelatedInstances(List uses) private static Color GetColorAtMousePosition() { - var pos = Program.CursorPosOnScreen; + var pos = UiContentUpdate.CursorPosOnScreen; var x = (int)pos.X; var y = (int)pos.Y; @@ -694,6 +739,7 @@ private static Color GetColorAtMousePosition() private static Color _hoveredColor; private static bool _isHoveringColor; private static readonly Bitmap _bmp = new(1, 1); + public const string PopupId = "##colorEdit"; } public static class ColorUsage diff --git a/Editor/Gui/Interaction/CurveEditPopup.cs b/Editor/Gui/Interaction/CurveEditPopup.cs new file mode 100644 index 0000000000..87cc8ab0ba --- /dev/null +++ b/Editor/Gui/Interaction/CurveEditPopup.cs @@ -0,0 +1,75 @@ +using System.Drawing; +using System.Numerics; +using ImGuiNET; +using T3.Core.DataTypes; +using T3.Core.Operator; +using T3.Editor.Gui.InputUi; +using T3.Editor.Gui.InputUi.CombinedInputs; +using T3.Editor.Gui.Styling; +using Icon = T3.Editor.Gui.Styling.Icon; + +namespace T3.Editor.Gui.Interaction; + +public static class CurveEditPopup +{ + public static bool DrawPopupIndicator(SymbolChild.Input input, ref Curve curve, Vector2 keepPositionForIcon, bool cloneIfModified, out InputEditStateFlags result) + { + var openPop = false; + var keepPositionForContentBelow = ImGui.GetCursorPos(); + ImGui.SetCursorPos(keepPositionForIcon); + var iconSize = ImGui.GetFrameHeight() * Vector2.One; + ImGui.BeginChild("Icon", iconSize); + var clicked = CustomComponents.IconButton(Icon.PopUp, iconSize); + if (clicked) + { + openPop = true; + } + + ImGui.EndChild(); + ImGui.SetCursorPos(keepPositionForContentBelow); + if (openPop) + { + ImGui.OpenPopup(CurvePopupId); + ImGui.SetNextWindowSize(new Vector2(500, 400)); + } + + var isOpen = ImGui.IsPopupOpen(CurvePopupId); + + result= DrawPopup(ref curve, input, cloneIfModified); + return isOpen; + } + + private static InputEditStateFlags DrawPopup(ref Curve curve, SymbolChild.Input input, + bool cloneIfModified) + { + + var edited = InputEditStateFlags.Nothing; + //var componentId = ImGui.GetID("curveEditor"); + + if (ImGui.BeginPopup(CurvePopupId)) + { + // if (_activatedComponentId != componentId) + // { + // _activatedComponentId = componentId; + // } + + edited= CurveInputEditing.DrawCanvasForCurve(ref curve, input, cloneIfModified, T3Ui.EditingFlags.ExpandVertically); + ImGui.EndPopup(); + } + else + { + // if (_activatedComponentId == componentId) + // { + // _activatedComponentId = 0; + // } + } + + return edited; + } + + + private static readonly CurveInputEditing.CurveInteraction.SingleCurveEditCanvas _singleCurveCanvas = new() { ImGuiTitle = "canvasPopup"}; + private const string CurvePopupId= "##CurvePopup"; + // private static uint _activatedComponentId; + private static readonly Bitmap _bmp = new(1, 1); +} \ No newline at end of file diff --git a/Editor/Gui/Interaction/InfinitySliderOverlay.cs b/Editor/Gui/Interaction/InfinitySliderOverlay.cs new file mode 100644 index 0000000000..a1133ffa66 --- /dev/null +++ b/Editor/Gui/Interaction/InfinitySliderOverlay.cs @@ -0,0 +1,258 @@ +using System; +using System.Numerics; +using System.Runtime.CompilerServices; +using ImGuiNET; +using T3.Core.Utils; +using T3.Editor.Gui.Styling; +using T3.Editor.Gui.UiHelpers; + +namespace T3.Editor.Gui.Interaction +{ + /// + /// Terminology + /// valueRange - delta value for complete revolution of current dial + /// tickInterval = Log10 delta vale between ticks. + /// + public static class InfinitySliderOverlay + { + public static void Draw(ref double roundedValue, bool restarted, Vector2 center, double min = double.NegativeInfinity, + double max = double.PositiveInfinity, + float scale = 0.1f, bool clamp = false) + { + var drawList = ImGui.GetForegroundDrawList(); + _io = ImGui.GetIO(); + + if (restarted) + { + _value = roundedValue; + _center = _io.MousePos; + _dampedDistance = 50; + _dampedAngleVelocity = 0; + _dampedModifierScaleFactor = 1; + _lastXOffset = 0; + _originalValue = roundedValue; + } + + var mouseYDistance = _center.Y - _io.MousePos.Y; // Vector2.Distance(_center, p1); + + // Update angle... + var mousePosX = _io.MousePos.X; + var xOffset = mousePosX - _center.X; + var deltaX = xOffset - _lastXOffset; + _lastXOffset = xOffset; + + _dampedAngleVelocity = MathUtils.Lerp(_dampedAngleVelocity, (float)deltaX, 0.06f); + + // Update radius and value range + _dampedDistance = mouseYDistance; + const int log10YDistance = 100; + var normalizedLogDistanceForLog10 = _dampedDistance / log10YDistance; + + // Value range and tick interval + _dampedModifierScaleFactor = MathUtils.Lerp(_dampedModifierScaleFactor, GetKeyboardScaleFactor(), 0.1f); + + var valueRange = (Math.Pow(10, normalizedLogDistanceForLog10)) * scale *0.25f * _dampedModifierScaleFactor * 600; + + var log10 = Math.Log10(valueRange); + var iLog10 = Math.Floor(log10); + var logRemainder = log10 - iLog10; + var tickValueInterval = Math.Pow(10, iLog10 - 1); + + const float width = 750; + + // Update value... + _value += deltaX / width * valueRange; + if (clamp) + _value = _value.Clamp(min, max); + + roundedValue = _io.KeyCtrl ? _value : Math.Round(_value / (tickValueInterval / 10)) * (tickValueInterval / 10); + + var rSize = new Vector2(width, 40); + var rCenter = new Vector2(mousePosX, _io.MousePos.Y - rSize.Y); + var rect = new ImRect(rCenter - rSize / 2, rCenter + rSize / 2); + + var numberOfTicks = valueRange / tickValueInterval; + var valueTickRemainder = MathUtils.Fmod(_value, tickValueInterval); + + // Draw scale range indicates + { + for (var yIndex = -2; yIndex < 4; yIndex++) + { + var centerPoint = new Vector2(mousePosX, _center.Y - log10YDistance * yIndex); + var v = Math.Pow(10, yIndex); + var label = $"× {v:G5}"; + var size = ImGui.CalcTextSize(label); + + var fade = (MathF.Abs(centerPoint.Y - rCenter.Y) / 50).Clamp(0, 1); + + var boxSize = new Vector2(80, 100); + var labelCenter = centerPoint + new Vector2(10); + drawList.AddRectFilled(centerPoint - boxSize / 2, centerPoint + boxSize / 2 + new Vector2(0, -1), UiColors.BackgroundFull.Fade(0.3f * fade), + 3); + drawList.AddText( + labelCenter - new Vector2(size.X / 2 + 10, 18), + UiColors.ForegroundFull.Fade(fade * 0.6f), + label); + } + } + + // Draw ticks with labels + drawList.AddRectFilled(rCenter - rSize / 2, rCenter + rSize / 2, UiColors.BackgroundFull.Fade(0.8f), 8); + for (var tickIndex = -(int)numberOfTicks / 2; tickIndex < numberOfTicks / 2; tickIndex++) + { + var f = MathF.Pow(MathF.Abs(tickIndex / ((float)numberOfTicks / 2)), 2f); + var negF = 1 - f; + var valueAtTick = tickIndex * tickValueInterval + _value - valueTickRemainder; + GetXForValueIfVisible(valueAtTick, valueRange, mousePosX, width, out var tickX); + var isPrimary = Math.Abs(MathUtils.Fmod(valueAtTick + tickValueInterval * 5, tickValueInterval * 10) - tickValueInterval * 5) < + tickValueInterval / 10; + var isPrimary2 = Math.Abs(MathUtils.Fmod(valueAtTick + tickValueInterval * 50, tickValueInterval * 100) - tickValueInterval * 50) < + tickValueInterval / 100; + + var fff = MathUtils.SmootherStep(1, 0.8f, (float)logRemainder); + drawList.AddLine( + new Vector2(tickX, rect.Max.Y), + new Vector2(tickX, rect.Max.Y - 10), + UiColors.ForegroundFull.Fade(negF * (isPrimary ? 1 : 0.5f * fff)), + 1 + ); + + var font = isPrimary2 ? Fonts.FontBold : Fonts.FontNormal; + var v = Math.Abs(valueAtTick) < 0.0001 ? 0 : valueAtTick; + var label = $"{v:G5}"; + + var ff = (1 - (float)logRemainder * 2); + if (isPrimary2 || ff < 1) + { + ImGui.PushFont(font); + var size = ImGui.CalcTextSize(label); + ImGui.PopFont(); + + drawList.AddText(font, + font.FontSize, + new Vector2(tickX - 1 - size.X / 2, rect.Max.Y - 30), + UiColors.BackgroundFull.Fade(negF * ff), + label); + + drawList.AddText(font, + font.FontSize, + new Vector2(tickX - size.X / 2 + 1, rect.Max.Y - 30), + UiColors.BackgroundFull.Fade(negF * ff), + label); + + var fadeOut = (isPrimary ? 1 : ff) * 0.7f; + drawList.AddText(font, + font.FontSize, + new Vector2(tickX - size.X / 2, rect.Max.Y - 30), + UiColors.ForegroundFull.Fade(negF * (isPrimary2 ? 1 : fadeOut)), + label); + } + } + + + + // Draw Value range + { + var rangeMin = _value - valueRange / 2; + var rangeMax = _value + valueRange / 2; + if (min > -9999999 && max < 9999999 && !(min < rangeMin && max < rangeMin || (min > rangeMax && max > rangeMax))) + { + var visibleMinValue = Math.Max(min, rangeMin); + var visibleMaxValue = Math.Min(max, rangeMax); + + var y = rect.Max.Y - 1.5f; + GetXForValueIfVisible(visibleMinValue, valueRange, mousePosX, width, out var visibleMinX); + GetXForValueIfVisible(visibleMaxValue, valueRange, mousePosX, width, out var visibleMaxX); + drawList.AddLine(new Vector2(visibleMinX, y), + new Vector2(visibleMaxX, y), + UiColors.ForegroundFull.Fade(0.5f), + 2); + } + } + + // Current value at mouse + { + if (!GetXForValueIfVisible(roundedValue, valueRange, mousePosX, width, out var screenX)) + return; + + ImGui.PushFont(Fonts.FontLarge); + var label = $"{roundedValue:G7}\n"; + var labelSize = ImGui.CalcTextSize(label); + drawList.AddRectFilled( + new Vector2(screenX - labelSize.X / 2 - 10, rect.Max.Y), + new Vector2(screenX + labelSize.X / 2 + 10, rect.Max.Y + 25), + UiColors.BackgroundFull.Fade(0.5f), + 5 + ); + drawList.AddLine(new Vector2(screenX, rect.Min.Y), + new Vector2(screenX, rect.Max.Y + 5), + UiColors.StatusActivated, + 1 + ); + drawList.AddText(new Vector2(screenX - labelSize.X / 2, rect.Max.Y + 3), + Color.White.Fade(1), + label + ); + ImGui.PopFont(); + } + + // Draw previous value + { + if (GetXForValueIfVisible(_originalValue, valueRange, mousePosX, width, out var visibleMinX)) + { + var y = rect.Min.Y; + + drawList.AddTriangleFilled(new Vector2(visibleMinX, y+4), + new Vector2(visibleMinX+4, y), + new Vector2(visibleMinX-4, y), + UiColors.ForegroundFull); + } + } + } + + private static bool IsValueVisible(double value, double valueRange) + { + return Math.Abs(_value - value) <= valueRange / 2 + 0.001; + } + + private static float GetXForValue(double value, double valueRange, float mousePosX) + { + return (float)((_value - value) / valueRange + mousePosX); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool GetXForValueIfVisible(double v, double valueRange, float mouseX, float width, out float x) + { + x = float.NaN; + if (!IsValueVisible(v, valueRange)) + return false; + + x = MathF.Floor((float)((v - _value) / valueRange * width + mouseX)); + return true; + } + + private static double GetKeyboardScaleFactor() + { + if (_io.KeyAlt) + return 10; + + if (_io.KeyShift) + return 0.1; + + return 1; + } + + /** The precise value before rounding. This used for all internal calculations. */ + private static double _value; + + private static float _dampedDistance; + private static Vector2 _center = Vector2.Zero; + private static float _dampedAngleVelocity; + private static double _lastXOffset; + private static double _dampedModifierScaleFactor; + + private static double _originalValue; + + private static ImGuiIOPtr _io; + } +} \ No newline at end of file diff --git a/Editor/Gui/Interaction/RadialSliderOverlay.cs b/Editor/Gui/Interaction/RadialSliderOverlay.cs new file mode 100644 index 0000000000..dab93bb15d --- /dev/null +++ b/Editor/Gui/Interaction/RadialSliderOverlay.cs @@ -0,0 +1,308 @@ +using System; +using System.Numerics; +using ImGuiNET; +using T3.Core.Utils; +using T3.Editor.Gui.Styling; + +namespace T3.Editor.Gui.Interaction +{ + /// + /// Draws a circular dial to manipulate values with various speeds. + /// + /// The manipulation area centers left and right of the current mouse position + /// on the ring -- with a value jump on the opposite side. + /// + /// + /// + /// Terminology + /// range - normalized angle from -0.5 ... 0.5 with 0 at current value + /// valueRange - delta value for complete revolution of current dial + /// tickInterval = Log10 delta vale between ticks. + /// + public static class RadialSliderOverlay + { + public static void Draw(ref double roundedValue, bool restarted, Vector2 center, double min = double.NegativeInfinity, + double max = double.PositiveInfinity, + float scale = 0.1f, bool clamp = false) + { + var drawList = ImGui.GetForegroundDrawList(); + _io = ImGui.GetIO(); + + if (restarted) + { + _value = roundedValue; + //_mousePositions.Clear(); + _center = _io.MousePos; + _dampedRadius = 50; + _dampedAngleVelocity = 0; + _dampedModifierScaleFactor = 1; + _lastValueAngle = 0; + _framesSinceLastMove = 120; + _originalValue = roundedValue; + _framesSinceStart = 0; + } + + + //_mousePositions.Add(_io.MousePos); + // if (_mousePositions.Count > 100) + // { + // _mousePositions.RemoveAt(0); + // } + _framesSinceStart++; + // + // if (_framesSinceStart <= 1) + // return; + + var p1 = _io.MousePos; + var mousePosRadius = Vector2.Distance(_center, p1); + + // Update angle... + var dir = p1 - _center; + var mouseAngle = MathF.Atan2(dir.X, dir.Y); + var deltaAngle = DeltaAngle(mouseAngle, _lastValueAngle); + _lastValueAngle = mouseAngle; + + var hasMoved = Math.Abs(deltaAngle) > 0.015f; + if (hasMoved) + { + + _framesSinceLastMove = 0; + } + else + { + //if(Math.Abs(mousePosRadius - _dampedRadius) > 40) + _framesSinceLastMove++; + } + + _dampedAngleVelocity = MathUtils.Lerp(_dampedAngleVelocity, (float)deltaAngle, 0.06f); + + // Update radius and value range + const float maxRadius = 2500; + var angleDampingFromDelay = (_framesSinceStart > 30 ? MathF.Pow(MathUtils.SmootherStep(2, 15, _framesSinceLastMove),4) : 1) * 0.07f; + var angleDampingFromRadiusDistance = MathF.Pow(MathUtils.SmootherStep(40, 70, Math.Abs(mousePosRadius - _dampedRadius)), 4); + _dampedRadius = MathUtils.Lerp(_dampedRadius, mousePosRadius.Clamp(40f,maxRadius), angleDampingFromDelay * angleDampingFromRadiusDistance); + var normalizedClampedRadius = ( _dampedRadius/1000).Clamp(0.0f, 1); + + // Value range and tick interval + _dampedModifierScaleFactor = MathUtils.Lerp(_dampedModifierScaleFactor, GetKeyboardScaleFactor(), 0.1f); + var valueRange = (Math.Pow(3 * (normalizedClampedRadius ), 3)) * 50 * scale * _dampedModifierScaleFactor; + var tickInterval = Math.Pow(10, (int)Math.Log10(valueRange * 250 / _dampedRadius) - 2) ; + + + // Update value... + _value += deltaAngle / (Math.PI * 2) * valueRange; + roundedValue = _io.KeyCtrl ? _value : Math.Round(_value / (tickInterval)) * tickInterval; + + var numberOfTicks = valueRange / tickInterval; + var anglePerTick = 2*Math.PI / numberOfTicks; + + var valueTickOffsetFactor = MathUtils.Fmod(_value, tickInterval) / tickInterval; + var tickRatioAlignmentAngle = anglePerTick * valueTickOffsetFactor ; + + drawList.AddCircle(_center, _dampedRadius+25, UiColors.BackgroundFull.Fade(0.1f), 128, 50); + + // Draw ticks with labels + for (int tickIndex = -(int)numberOfTicks/2; tickIndex < numberOfTicks/2; tickIndex++) + { + var f = MathF.Pow(MathF.Abs(tickIndex / ((float)numberOfTicks/2)), 0.5f); + var negF = 1 - f; + var tickAngle = tickIndex * anglePerTick - mouseAngle - tickRatioAlignmentAngle ; + var direction = new Vector2(MathF.Sin(-(float)tickAngle), MathF.Cos(-(float)tickAngle)); + var valueAtTick = _value + (tickIndex * anglePerTick - tickRatioAlignmentAngle) / (2 * Math.PI) * valueRange; + var isPrimary = Math.Abs(MathUtils.Fmod(valueAtTick + tickInterval * 5, tickInterval * 10) - tickInterval * 5) < tickInterval / 10; + var isPrimary2 = Math.Abs(MathUtils.Fmod(valueAtTick + tickInterval * 50, tickInterval * 100) - tickInterval * 50) < tickInterval / 100; + + drawList.AddLine(direction * _dampedRadius + _center, + direction * (_dampedRadius + (isPrimary ? 10 : 5f)) + _center, + UiColors.ForegroundFull.Fade(negF * (isPrimary ? 1 : 0.5f)), + 1 + ); + + if (!isPrimary) + continue; + + var font = isPrimary2 ? Fonts.FontBold : Fonts.FontSmall; + var v = Math.Abs(valueAtTick) < 0.0001 ? 0 : valueAtTick; + var label = $"{v:G5}"; + + ImGui.PushFont(font); + var size = ImGui.CalcTextSize(label); + ImGui.PopFont(); + + drawList.AddText(font, + font.FontSize, + direction * (_dampedRadius + 30) + _center - size/2, + UiColors.ForegroundFull.Fade(negF * (isPrimary2 ? 1 : 0.3f)), + label); + } + + // Draw previous value + { + var visible = IsValueVisible(_originalValue, valueRange); + if (visible) + { + var originalValueAngle= ComputeAngleForValue(_originalValue, valueRange, mouseAngle); + var direction = new Vector2(MathF.Sin(originalValueAngle), MathF.Cos(originalValueAngle)); + drawList.AddLine(direction * _dampedRadius + _center, + direction * (_dampedRadius - 10) + _center, + UiColors.StatusActivated.Fade(0.8f), + 2 + ); + } + } + + // Draw Value range + { + var rangeMin = _value - valueRange * 0.45f; + var rangeMax = _value + valueRange * 0.45f; + if (!(min < rangeMin && max < rangeMin || (min > rangeMax && max > rangeMax))) + { + const float innerOffset = 4; + var minAngle= ComputeAngleForValue(Math.Max(min, rangeMin), valueRange, mouseAngle); + var maxAngle= ComputeAngleForValue(Math.Min(max, rangeMax), valueRange, mouseAngle); + + drawList.PathClear(); + var minVisible = GetDirectionForValueIfVisible(min, valueRange, mouseAngle, out var dirForMinIndicator); + if (minVisible) + { + drawList.PathLineTo(_center + dirForMinIndicator * (_dampedRadius - 10)); + } + + drawList.PathArcTo(_center, _dampedRadius-innerOffset, -minAngle + MathF.PI/2 , -maxAngle + MathF.PI/2, 90); + + var maxVisible = GetDirectionForValueIfVisible(max, valueRange, mouseAngle, out var dirForMaxIndicator); + if (maxVisible) + { + drawList.PathLineTo(_center + dirForMaxIndicator * (_dampedRadius - 10)); + } + drawList.PathStroke(UiColors.ForegroundFull.Fade(0.4f), ImDrawFlags.None, 2); + + if (!minVisible) + { + drawList.PathClear(); + drawList.PathArcTo(_center, _dampedRadius -innerOffset , -minAngle + MathF.PI/2 - 5 * MathUtils.ToRad , -minAngle + MathF.PI/2, 90); + drawList.PathStroke(UiColors.ForegroundFull.Fade(0.3f), ImDrawFlags.None, 2); + } + if (!maxVisible) + { + drawList.PathClear(); + drawList.PathArcTo(_center, _dampedRadius - innerOffset, -maxAngle + MathF.PI/2 + 5 * MathUtils.ToRad , -maxAngle + MathF.PI/2, 90); + drawList.PathStroke(UiColors.ForegroundFull.Fade(0.2f), ImDrawFlags.None, 2); + } + } + } + + // Current value at mouse + { + var dialFade = MathUtils.SmootherStep(60, 160, _dampedRadius); + var dialAngle= (float)( (_value - roundedValue) * (2 * Math.PI) / valueRange + mouseAngle); + _dampedDialValueAngle = MathUtils.LerpAngle(_dampedDialValueAngle, dialAngle, 0.4f); + var direction = new Vector2(MathF.Sin(_dampedDialValueAngle), MathF.Cos(_dampedDialValueAngle)); + drawList.AddLine(direction * _dampedRadius + _center, + direction * (_dampedRadius + 30) + _center, + UiColors.ForegroundFull.Fade(0.7f * dialFade), + 2 + ); + + var labelFade = MathUtils.SmootherStep(200, 300, _dampedRadius); + + drawList.AddText(Fonts.FontBold, + Fonts.FontBold.FontSize, + direction * (_dampedRadius - 40) + _center + new Vector2(-15,-Fonts.FontSmall.FontSize/2), + Color.White.Fade(labelFade * dialFade), + $"{roundedValue:0.00}\n" + ); + } + } + + private static bool IsValueVisible(double value, double valueRange) + { + return Math.Abs(_value - value) < valueRange * 0.45f; + } + + private static float ComputeAngleForValue(double value, double valueRange, float mouseAngle) + { + return (float)( (_value - value) * (2 * Math.PI) / valueRange + mouseAngle); + } + + private static bool GetDirectionForValueIfVisible(double value, double valueRange, float mouseAngle, out Vector2 direction) + { + direction = Vector2.Zero; + + if(!IsValueVisible(value, valueRange)) + return false; + + var angle = ComputeAngleForValue(value, valueRange, mouseAngle); + direction = new Vector2(MathF.Sin(angle), MathF.Cos(angle)); + return true; + } + + + private static double DeltaAngle(double angle1, double angle2) + { + angle1 = (angle1 + Math.PI) % (2 * Math.PI) - Math.PI; + angle2 = (angle2 + Math.PI) % (2 * Math.PI) - Math.PI; + + var delta = angle2 - angle1; + return delta switch + { + > Math.PI => delta - 2 * Math.PI, + < -Math.PI => delta + 2 * Math.PI, + _ => delta + }; + } + + + private static bool CalculateIntersection(Vector2 p1A, Vector2 p1B, Vector2 p2A, Vector2 p2B, out Vector2 intersection) + { + double a1 = p1B.Y - p1A.Y; + double b1 = p1A.X - p1B.X; + double c1 = a1 * p1A.X + b1 * p1A.Y; + + double a2 = p2B.Y - p2A.Y; + double b2 = p2A.X - p2B.X; + double c2 = a2 * p2A.X + b2 * p2A.Y; + + double determinant = a1 * b2 - a2 * b1; + + if (Math.Abs(determinant) < 1e-6) // Lines are parallel + { + intersection =Vector2.Zero; + return false; + } + + var x = (b2 * c1 - b1 * c2) / determinant; + var y = (a1 * c2 - a2 * c1) / determinant; + intersection = new Vector2((float)x, (float)y); + return true; + } + + + private static double GetKeyboardScaleFactor() + { + if (_io.KeyAlt) + return 10; + + if (_io.KeyShift) + return 0.1; + + return 1; + } + + /** The precise value before rounding. This used for all internal calculations. */ + private static double _value; + + private static float _dampedRadius; + private static Vector2 _center = Vector2.Zero; + private static float _dampedAngleVelocity; + private static double _lastValueAngle; + private static double _dampedModifierScaleFactor; + private static float _dampedDialValueAngle; + private static int _framesSinceLastMove; + private static double _originalValue; + //private static readonly List _mousePositions = new(100); + //private static ImDrawListPtr _drawList; + private static ImGuiIOPtr _io; + private static int _framesSinceStart; + } +} \ No newline at end of file diff --git a/Editor/Gui/Interaction/ScalableCanvas.cs b/Editor/Gui/Interaction/ScalableCanvas.cs index 89d0c5bac6..56466ae47e 100644 --- a/Editor/Gui/Interaction/ScalableCanvas.cs +++ b/Editor/Gui/Interaction/ScalableCanvas.cs @@ -245,8 +245,12 @@ public void SetScopeToCanvasArea(ImRect area, bool flipY = false, ScalableCanvas Scale = Vector2.One; } - ScaleTarget = (WindowSize - new Vector2(paddingX, paddingY)) / areaSize; - + ScaleTarget = (WindowSize - new Vector2(paddingX, paddingY)); + ScaleTarget.X = MathF.Max(ScaleTarget.X, 20); + ScaleTarget.Y = MathF.Max(ScaleTarget.Y, 20); + + ScaleTarget /= areaSize; + if (flipY) { ScaleTarget.Y *= -1; diff --git a/Editor/Gui/Interaction/SingleValueEdit.cs b/Editor/Gui/Interaction/SingleValueEdit.cs index 7860654641..0ac7a1f642 100644 --- a/Editor/Gui/Interaction/SingleValueEdit.cs +++ b/Editor/Gui/Interaction/SingleValueEdit.cs @@ -25,7 +25,7 @@ public static InputEditStateFlags Draw(ref int value, int min = int.MinValue, int max = int.MaxValue, bool clamp = false, - float scale = 0.1f, + float scale = 1f, string format = "{0:0}") { double doubleValue = value; @@ -116,15 +116,8 @@ public static InputEditStateFlags Draw(ref double value, SetState(InputStates.Inactive); break; } - - if (UserSettings.Config.UseJogDialControl) - { - JogDialOverlay.Draw(ref _editValue, (float)(ImGui.GetTime() - _timeOpened) < 0.1f, _center, min, max, scale, clamp); - } - else - { - SliderLadder.Draw(ref _editValue, io, min, max, scale, (float)(ImGui.GetTime() - _timeOpened), clamp, _center); - } + var restarted = (float)(ImGui.GetTime() - _timeOpened) < 0.1f; + DrawValueEditGizmo(ref _editValue, restarted,_center, min, max, clamp, scale); break; @@ -218,7 +211,7 @@ public static InputEditStateFlags Draw(ref double value, T3Ui.MouseWheelFieldHovered = true; ImGui.SetMouseCursor(ImGuiMouseCursor.ResizeEW); var dl = ImGui.GetForegroundDrawList(); - dl.AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), UiColors.Gray); + dl.AddRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax(), UiColors.StatusActivated); var wheel = io.MouseWheel; if (wheel == 0) @@ -235,12 +228,12 @@ public static InputEditStateFlags Draw(ref double value, } value += wheel * scale * 10 * factor; - _hovereddComponentModifiedByWheel = true; + _hoveredComponentModifiedByWheel = true; return InputEditStateFlags.Modified; } - var didModify = _hovereddComponentModifiedByWheel; - _hovereddComponentModifiedByWheel = false; + var didModify = _hoveredComponentModifiedByWheel; + _hoveredComponentModifiedByWheel = false; return didModify ? InputEditStateFlags.ModifiedAndFinished @@ -250,7 +243,7 @@ public static InputEditStateFlags Draw(ref double value, if (isHovered) { T3Ui.MouseWheelFieldHovered = true; - _hovereddComponentModifiedByWheel = false; + _hoveredComponentModifiedByWheel = false; _activeHoverComponentId = componentId; return InputEditStateFlags.Started; } @@ -260,7 +253,27 @@ public static InputEditStateFlags Draw(ref double value, return InputEditStateFlags.Nothing; } - private static bool _hovereddComponentModifiedByWheel; + public static void DrawValueEditGizmo(ref double editValue, bool restarted, Vector2 center, double min, double max, bool clamp, float scale) + { + switch (UserSettings.Config.ValueEditGizmo) + { + case UserSettings.ValueEditGizmos.InfinitySlider: + InfinitySliderOverlay.Draw(ref editValue, restarted, center, min, max, scale, clamp); + break; + case UserSettings.ValueEditGizmos.RadialSlider: + RadialSliderOverlay.Draw(ref editValue, restarted, center, min, max, scale, clamp); + break; + case UserSettings.ValueEditGizmos.JogDial: + JogDialOverlay.Draw(ref editValue, restarted, center, min, max, scale, clamp); + break; + case UserSettings.ValueEditGizmos.ValueLadder: + default: + SliderLadder.Draw(ref editValue, min, max, scale, (float)(ImGui.GetTime() - _timeOpened), clamp, center); + break; + } + } + + private static bool _hoveredComponentModifiedByWheel; private static void SetState(InputStates newState) { @@ -337,6 +350,9 @@ private static void DrawButtonWithDynamicLabel(string label, ref Vector2 size) var color1 = Color.GetStyleColor(ImGuiCol.Text).Fade(ImGui.GetStyle().Alpha); var keepPos = ImGui.GetCursorScreenPos(); ImGui.Button("##dial", size); + if (string.IsNullOrEmpty(label)) + return; + ImGui.GetWindowDrawList().AddText(keepPos + new Vector2(4, 4), color1, label); } diff --git a/Editor/Gui/Interaction/SliderLadder.cs b/Editor/Gui/Interaction/SliderLadder.cs index 0e8c2fe62a..d85e3b7313 100644 --- a/Editor/Gui/Interaction/SliderLadder.cs +++ b/Editor/Gui/Interaction/SliderLadder.cs @@ -40,8 +40,9 @@ public RangeDef(float scaleFactor, string label) private const float LockDistance = 100; - public static void Draw(ref double editValue, ImGuiIOPtr io, double min, double max, float scale, float timeSinceVisible, bool clamp, Vector2 center) + public static void Draw(ref double editValue, double min, double max, float scale, float timeSinceVisible, bool clamp, Vector2 center) { + var io = ImGui.GetIO(); var foreground = ImGui.GetForegroundDrawList(); const double initialDelay = 0.2; @@ -129,7 +130,7 @@ public static void Draw(ref double editValue, ImGuiIOPtr io, double min, double if (io.KeyAlt) { ImGui.PushFont(Fonts.FontSmall); - foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "x0.01"); + foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "×0.01"); ImGui.PopFont(); scale *= 0.01f; @@ -137,7 +138,7 @@ public static void Draw(ref double editValue, ImGuiIOPtr io, double min, double else if (io.KeyShift) { ImGui.PushFont(Fonts.FontSmall); - foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "x10"); + foreground.AddText(ImGui.GetMousePos() + new Vector2(10, 10), UiColors.Gray, "×10"); ImGui.PopFont(); scale *= 10f; diff --git a/Editor/Gui/Interaction/StartupCheck/StartUp.cs b/Editor/Gui/Interaction/StartupCheck/StartUp.cs index 4b2c3d4dfe..7db90f2d55 100644 --- a/Editor/Gui/Interaction/StartupCheck/StartUp.cs +++ b/Editor/Gui/Interaction/StartupCheck/StartUp.cs @@ -92,7 +92,7 @@ private static void ShowMessageBox() } } - private const string HelpUrl = "https://github.com/still-scene/t3/wiki/installation#setup-and-installation"; + private const string HelpUrl = "https://github.com/tooll3/t3/wiki/installation#setup-and-installation"; private const string StartUpLockFilePath = @".t3\startingUp"; } } \ No newline at end of file diff --git a/Editor/Gui/Interaction/StartupCheck/StartupValidation.cs b/Editor/Gui/Interaction/StartupCheck/StartupValidation.cs index 68a93fef37..f834a523c2 100644 --- a/Editor/Gui/Interaction/StartupCheck/StartupValidation.cs +++ b/Editor/Gui/Interaction/StartupCheck/StartupValidation.cs @@ -18,6 +18,7 @@ public static class StartupValidation { public static void CheckInstallation() { + var checks = new Check[] { new() @@ -27,10 +28,11 @@ public static void CheckInstallation() @"Resources\", @"Resources\t3-editor\images\t3-icons.png", @"Resources\t3-editor\images\t3.ico", + @"Resources\t3-editor\images\t3-SplashScreen.png", @"Resources\t3-editor\fonts\Roboto-Regular.ttf", }, Message = @"Please make sure to set the correct start up directory.\n ", - URL = "https://github.com/still-scene/t3/wiki/installation#setting-the-startup-directory-in-visual-studio", + URL = "https://github.com/tooll3/t3/wiki/installation#setting-the-startup-directory-in-visual-studio", }, new() { @@ -38,9 +40,10 @@ public static void CheckInstallation() { LayoutHandling.LayoutPath + "layout1.json", @"Editor\bin\Release\net6.0-windows\bass.dll", + @"Editor\bin\Debug\net6.0-windows\bass.dll", }, Message = "Please run Install/install.bat.", - URL = "https://github.com/still-scene/t3/wiki/installation#setup-and-installation", + URL = "https://github.com/tooll3/t3/wiki/installation#setup-and-installation", }, new() { @@ -49,7 +52,7 @@ public static void CheckInstallation() @"Player\bin\Release\net6.0-windows\Player.exe", }, Message = "This will prevent you from exporting as executable.\nPlease rebuild your solution.", - URL = "https://github.com/still-scene/t3/wiki/installation#setup-and-installation", + URL = "https://github.com/tooll3/t3/wiki/installation#setup-and-installation", } }; var _ = checks.Any(check => !check.Do()); @@ -115,7 +118,8 @@ public bool Do() var sb = new StringBuilder(); - sb.Append($"Startup folder is:\n{EditorUi.Instance.StartupPath}\n\n"); + var startupPath = Path.GetFullPath("."); + sb.Append($"Startup folder is:\n{startupPath}\n\n"); sb.Append($"We can't find the following files...\n\n {string.Join("\n ", missingPaths)}"); sb.Append("\n\n"); diff --git a/Editor/Gui/Interaction/TransformGizmos/TransformGizmoHandling.cs b/Editor/Gui/Interaction/TransformGizmos/TransformGizmoHandling.cs index ce46f057bb..5898411a10 100644 --- a/Editor/Gui/Interaction/TransformGizmos/TransformGizmoHandling.cs +++ b/Editor/Gui/Interaction/TransformGizmos/TransformGizmoHandling.cs @@ -13,6 +13,7 @@ using T3.Editor.Gui.Styling; using T3.Editor.Gui.UiHelpers; using T3.Editor.Gui.Windows; +using T3.Editor.UiModel; using Color = T3.Editor.Gui.Styling.Color; using Vector2 = System.Numerics.Vector2; using Vector3 = System.Numerics.Vector3; diff --git a/Editor/Gui/Interaction/UserAction.cs b/Editor/Gui/Interaction/UserAction.cs index 502fcd9102..901485c7b5 100644 --- a/Editor/Gui/Interaction/UserAction.cs +++ b/Editor/Gui/Interaction/UserAction.cs @@ -1,339 +1,372 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using ImGuiNET; using T3.Core.IO; -namespace T3.Editor.Gui.Interaction +namespace T3.Editor.Gui.Interaction; + +/// +/// UserAction represent single atomic commands that can be mapped to a keyboard shortcuts +/// +/// +public enum UserActions { - /// - /// UserAction represent single atomic commands that can be mapped to a keyboard shortcuts - /// - /// - public enum UserActions - { - // General - Undo, - Redo, - Save, - FocusSelection, - DeleteSelection, - CopyToClipboard, - PasteFromClipboard, - New, - - // Playback - PlaybackForward, - PlaybackForwardHalfSpeed, - PlaybackBackwards, - PlaybackNextFrame, - PlaybackPreviousFrame, - PlaybackStop, - PlaybackToggle, - PlaybackJumpBack, - PlaybackJumpToNextKeyframe, - PlaybackJumpToPreviousKeyframe, - PlaybackJumpToEndTime, - PlaybackJumpToStartTime, - - // Timeline - SetStartTime, - SetEndTime, - InsertKeyframe, - InsertKeyframeWithIncrement, - - ToggleAnimationPinning, - - - // Graph - PinToOutputWindow, - DisplayImageAsBackground, - ClearBackgroundImage, - Duplicate, - LayoutSelection, - ToggleDisabled, - ToggleBypassed, - AddAnnotation, - - ToggleSnapshotControl, - - ScrollLeft, - ScrollRight, - ScrollUp, - ScrollDown, - ZoomIn, - ZoomOut, - - NavigateBackwards, - NavigateForward, - - SelectToAbove, - SelectToRight, - SelectToBelow, - SelectToLeft, - - SearchGraph, + // General + Undo, + Redo, + Save, + FocusSelection, + DeleteSelection, + CopyToClipboard, + PasteFromClipboard, + New, + + // Playback + PlaybackForward, + PlaybackForwardHalfSpeed, + PlaybackBackwards, + PlaybackNextFrame, + PlaybackPreviousFrame, + PlaybackStop, + PlaybackToggle, + PlaybackJumpBack, + PlaybackJumpToNextKeyframe, + PlaybackJumpToPreviousKeyframe, + PlaybackJumpToEndTime, + PlaybackJumpToStartTime, + + // Timeline + SetStartTime, + SetEndTime, + InsertKeyframe, + InsertKeyframeWithIncrement, + TapBeatSync, + TapBeatSyncMeasure, + + ToggleAnimationPinning, + + // Graph + PinToOutputWindow, + DisplayImageAsBackground, + ClearBackgroundImage, + Duplicate, + LayoutSelection, + ToggleDisabled, + ToggleBypassed, + AddAnnotation, + AddComment, + + ToggleSnapshotControl, + + ScrollLeft, + ScrollRight, + ScrollUp, + ScrollDown, + ZoomIn, + ZoomOut, + + NavigateBackwards, + NavigateForward, + + SelectToAbove, + SelectToRight, + SelectToBelow, + SelectToLeft, + + SearchGraph, + + // Layout and window management + ToggleAllUiElements, + ToggleVariationsWindow, + ToggleFullscreen, + ToggleFocusMode, + + LoadLayout0, + LoadLayout1, + LoadLayout2, + LoadLayout3, + LoadLayout4, + LoadLayout5, + LoadLayout6, + LoadLayout7, + LoadLayout8, + LoadLayout9, + SaveLayout0, + SaveLayout1, + SaveLayout2, + SaveLayout3, + SaveLayout4, + SaveLayout5, + SaveLayout6, + SaveLayout7, + SaveLayout8, + SaveLayout9, + + LoadBookmark0, + LoadBookmark1, + LoadBookmark2, + LoadBookmark3, + LoadBookmark4, + LoadBookmark5, + LoadBookmark6, + LoadBookmark7, + LoadBookmark8, + LoadBookmark9, + SaveBookmark0, + SaveBookmark1, + SaveBookmark2, + SaveBookmark3, + SaveBookmark4, + SaveBookmark5, + SaveBookmark6, + SaveBookmark7, + SaveBookmark8, + SaveBookmark9, +} + +public static class UserActionRegistry +{ + public static readonly HashSet DeferredActions = new HashSet(); - // Layout and window management - ToggleFocusMode, - ToggleVariationsWindow, - - LoadLayout0, - LoadLayout1, - LoadLayout2, - LoadLayout3, - LoadLayout4, - LoadLayout5, - LoadLayout6, - LoadLayout7, - LoadLayout8, - LoadLayout9, - SaveLayout0, - SaveLayout1, - SaveLayout2, - SaveLayout3, - SaveLayout4, - SaveLayout5, - SaveLayout6, - SaveLayout7, - SaveLayout8, - SaveLayout9, - - LoadBookmark0, - LoadBookmark1, - LoadBookmark2, - LoadBookmark3, - LoadBookmark4, - LoadBookmark5, - LoadBookmark6, - LoadBookmark7, - LoadBookmark8, - LoadBookmark9, - SaveBookmark0, - SaveBookmark1, - SaveBookmark2, - SaveBookmark3, - SaveBookmark4, - SaveBookmark5, - SaveBookmark6, - SaveBookmark7, - SaveBookmark8, - SaveBookmark9, - + public static bool WasActionQueued(UserActions action) + { + if (!DeferredActions.Contains(action)) + return false; + DeferredActions.Remove(action); + return true; } +} - public static class UserActionRegistry +public class KeyboardBinding +{ + public static void InitFrame() { - public static readonly HashSet DeferredActions = new HashSet(); - - public static bool WasActionQueued(UserActions action) + if (!_initialized) { - if (!DeferredActions.Contains(action)) - return false; - - DeferredActions.Remove(action); - return true; + InitializeShortcutLabels(); + _initialized = true; } + + _anyKeysPressed = ImGui.GetIO().KeysDown.Count > 0; } - public class KeyboardBinding - { - public readonly UserActions Action; - public bool NeedsWindowFocus; - public bool NeedsWindowHover; - public bool KeyPressOnly; - public readonly KeyCombination Combination; + private readonly UserActions _action; + private bool _needsWindowFocus; + private bool _needsWindowHover; + private readonly bool _keyPressOnly; + private readonly KeyCombination _combination; + private static bool _initialized; - public static bool Triggered(UserActions action) - { - if (!_anyKeysPressed) - return false; + public static bool Triggered(UserActions action) + { + // Checking all bindings is expensive, so we only do this if any keys are pressed. + if (!_anyKeysPressed) + return false; - if (ImGui.IsAnyItemActive()) - return false; + // Prevent keyboard short-cuts while inputs are active + if (ImGui.IsAnyItemActive()) + return false; - var io = ImGui.GetIO(); - foreach (var binding in Bindings) - { - if (binding.Action != action) - continue; + var io = ImGui.GetIO(); + foreach (var binding in _bindings) + { + if (binding._action != action) + continue; - if (binding.NeedsWindowFocus && !ImGui.IsWindowFocused(ImGuiFocusedFlags.ChildWindows)) - continue; + if (binding._needsWindowFocus && !ImGui.IsWindowFocused(ImGuiFocusedFlags.ChildWindows)) + continue; - if (binding.NeedsWindowHover && !ImGui.IsWindowHovered(ImGuiHoveredFlags.ChildWindows)) - continue; + if (binding._needsWindowHover && !ImGui.IsWindowHovered(ImGuiHoveredFlags.ChildWindows)) + continue; - var c = binding.Combination; + var kc = binding._combination; - var isKeyPressed = (!binding.KeyPressOnly || ImGui.IsKeyPressed((ImGuiKey)c.Key, false)); - if (ImGui.IsKeyPressed((ImGuiKey)c.Key, false) - && isKeyPressed - && ((!c.Alt && !io.KeyAlt) || (c.Alt && io.KeyAlt)) // There is probably a smarty way to express this. - && ((!c.Ctrl && !io.KeyCtrl) || (c.Ctrl && io.KeyCtrl)) - && ((!c.Shift && !io.KeyShift) || (c.Shift && io.KeyShift)) - ) - return true; + var isKeyPressed = (!binding._keyPressOnly || ImGui.IsKeyPressed((ImGuiKey)kc.Key, false)); + if (ImGui.IsKeyPressed((ImGuiKey)kc.Key, false) + && isKeyPressed + && (!kc.Alt && !io.KeyAlt || kc.Alt && io.KeyAlt) + && (!kc.Ctrl && !io.KeyCtrl || kc.Ctrl && io.KeyCtrl) + && (!kc.Shift && !io.KeyShift || kc.Shift && io.KeyShift) + ) + { + return true; } - - return false; } - public static string ListKeyboardShortcuts(UserActions action, bool showLabel = true) - { - var bindings = Bindings.FindAll(b => b.Action == action); - if (bindings.Count == 0) - return ""; - - var shortCuts = bindings.Select(binding => binding.Combination.ToString()).ToList(); - return (showLabel - ? (bindings.Count == 1 - ? "Short cut: " - : "Short cuts ") - : "") - + string.Join(" and ", shortCuts); - } + return false; + } - public class KeyCombination + private static readonly Dictionary _keyboardShortCutLabels = new(); + + public static void InitializeShortcutLabels() + { + _keyboardShortCutLabels.Clear(); + foreach (var action in Enum.GetValues()) { - public KeyCombination(Key key, bool ctrl = false, bool alt = false, bool shift = false) - { - Key = key; - Ctrl = ctrl; - Alt = alt; - Shift = shift; - } + var bindings = _bindings.FindAll(b => b._action == action); + var shortCuts = bindings.Select(binding => binding._combination.ToString()).ToList(); - public readonly bool Ctrl; - public readonly bool Alt; - public readonly bool Shift; - public readonly Key Key; + if (shortCuts.Count == 0) + continue; - public override string ToString() - { - return (Ctrl ? "Ctrl+" : "") - + (Alt ? "Alt+" : "") - + (Shift ? "Shift+" : "") - + Key; - } + _keyboardShortCutLabels[action] = string.Join(" and ", shortCuts); } + } + + public static string ListKeyboardShortcuts(UserActions action, bool showLabel = true) + { + if (!_keyboardShortCutLabels.TryGetValue(action, out var shortCuts)) + return string.Empty; + + return (showLabel + ? (shortCuts.Contains("and") + ? "Short cut: " + : "Short cuts ") + : String.Empty) + + string.Join(" and ", shortCuts); + } - private KeyboardBinding(UserActions action, KeyCombination combination, bool needsWindowFocus = false, bool keyPressOnly = false) + private class KeyCombination + { + public KeyCombination(Key key, bool ctrl = false, bool alt = false, bool shift = false) { - Action = action; - Combination = combination; - NeedsWindowFocus = needsWindowFocus; - KeyPressOnly = keyPressOnly; + Key = key; + Ctrl = ctrl; + Alt = alt; + Shift = shift; } - private static readonly List Bindings - = new() - { - // Global - new KeyboardBinding(UserActions.Save, new KeyCombination(Key.S, ctrl: true)), - new KeyboardBinding(UserActions.FocusSelection, new KeyCombination(Key.F)) { NeedsWindowHover = true }, - new KeyboardBinding(UserActions.Duplicate, new KeyCombination(Key.D, ctrl: true)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.DeleteSelection, new KeyCombination(Key.Delete)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.DeleteSelection, new KeyCombination(Key.Backspace)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.CopyToClipboard, new KeyCombination(Key.C, ctrl: true)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.PasteFromClipboard, new KeyCombination(Key.V, ctrl: true)) { NeedsWindowFocus = true }, - - // Playback - new KeyboardBinding(UserActions.PlaybackForward, new KeyCombination(Key.L)), - new KeyboardBinding(UserActions.PlaybackForwardHalfSpeed, new KeyCombination(Key.L, shift: true)), - new KeyboardBinding(UserActions.PlaybackBackwards, new KeyCombination(Key.J)), - new KeyboardBinding(UserActions.PlaybackStop, new KeyCombination(Key.K)), - new KeyboardBinding(UserActions.PlaybackToggle, new KeyCombination(Key.Space)), // TODO: Fixme! - new KeyboardBinding(UserActions.PlaybackPreviousFrame, new KeyCombination(Key.CursorLeft, shift: true)), - new KeyboardBinding(UserActions.PlaybackNextFrame, new KeyCombination(Key.CursorRight, shift: true)), - new KeyboardBinding(UserActions.PlaybackJumpToStartTime, new KeyCombination(Key.Home)), - new KeyboardBinding(UserActions.PlaybackJumpToNextKeyframe, new KeyCombination(Key.Period)), - new KeyboardBinding(UserActions.PlaybackJumpToPreviousKeyframe, new KeyCombination(Key.Comma)), - new KeyboardBinding(UserActions.PlaybackNextFrame, new KeyCombination(Key.CursorRight, shift: true)), - new KeyboardBinding(UserActions.PlaybackJumpBack, new KeyCombination(Key.B)), - - new KeyboardBinding(UserActions.Undo, new KeyCombination(Key.Z, ctrl: true)), - new KeyboardBinding(UserActions.Redo, new KeyCombination(Key.Z, ctrl: true, shift: true)), - - // Timeline - new KeyboardBinding(UserActions.InsertKeyframe, new KeyCombination(Key.C)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.InsertKeyframeWithIncrement, new KeyCombination(Key.C, shift: true)), - new KeyboardBinding(UserActions.ToggleAnimationPinning, new KeyCombination(Key.K, shift: true)), - - // Graph window - new KeyboardBinding(UserActions.ToggleDisabled, new KeyCombination(Key.D, shift:true)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.ToggleBypassed, new KeyCombination(Key.B, shift:true)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.PinToOutputWindow, new KeyCombination(Key.P)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.DisplayImageAsBackground, new KeyCombination(Key.P, ctrl:true)) { NeedsWindowFocus = false }, - new KeyboardBinding(UserActions.ClearBackgroundImage, new KeyCombination(Key.P, ctrl:true, shift: true)) { NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.LayoutSelection, new KeyCombination(Key.G)), - - new KeyboardBinding(UserActions.AddAnnotation, new KeyCombination(Key.A, shift:true)){ NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.ToggleVariationsWindow, new KeyCombination(Key.V, alt:true)){ NeedsWindowFocus = false }, - new KeyboardBinding(UserActions.SearchGraph, new KeyCombination(Key.F, ctrl:true)){ NeedsWindowFocus = false }, - - new KeyboardBinding(UserActions.NavigateBackwards, new KeyCombination(Key.CursorLeft, alt:true)){ NeedsWindowFocus = false }, - new KeyboardBinding(UserActions.NavigateForward, new KeyCombination(Key.CursorRight, alt:true)){ NeedsWindowFocus = false }, - - new KeyboardBinding(UserActions.SelectToAbove, new KeyCombination(Key.CursorUp)){ NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.SelectToRight, new KeyCombination(Key.CursorRight)){ NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.SelectToBelow, new KeyCombination(Key.CursorDown)){ NeedsWindowFocus = true }, - new KeyboardBinding(UserActions.SelectToLeft, new KeyCombination(Key.CursorLeft)){ NeedsWindowFocus = true }, - - - // Layout and window management - new KeyboardBinding(UserActions.ToggleFocusMode, new KeyCombination(Key.Esc, shift: true)), - - new KeyboardBinding(UserActions.LoadBookmark1, new KeyCombination(Key.D1, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark2, new KeyCombination(Key.D2, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark3, new KeyCombination(Key.D3, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark4, new KeyCombination(Key.D4, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark5, new KeyCombination(Key.D5, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark6, new KeyCombination(Key.D6, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark7, new KeyCombination(Key.D7, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark8, new KeyCombination(Key.D8, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark9, new KeyCombination(Key.D9, ctrl: true)), - new KeyboardBinding(UserActions.LoadBookmark0, new KeyCombination(Key.D0, ctrl: true)), - - new KeyboardBinding(UserActions.SaveBookmark1, new KeyCombination(Key.D1, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark2, new KeyCombination(Key.D2, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark3, new KeyCombination(Key.D3, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark4, new KeyCombination(Key.D4, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark5, new KeyCombination(Key.D5, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark6, new KeyCombination(Key.D6, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark7, new KeyCombination(Key.D7, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark8, new KeyCombination(Key.D8, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark9, new KeyCombination(Key.D9, ctrl: true, shift: true)), - new KeyboardBinding(UserActions.SaveBookmark0, new KeyCombination(Key.D0, ctrl: true, shift: true)), - - new KeyboardBinding(UserActions.LoadLayout0, new KeyCombination(Key.F1)), - new KeyboardBinding(UserActions.LoadLayout1, new KeyCombination(Key.F2)), - new KeyboardBinding(UserActions.LoadLayout2, new KeyCombination(Key.F3)), - new KeyboardBinding(UserActions.LoadLayout3, new KeyCombination(Key.F4)), - new KeyboardBinding(UserActions.LoadLayout4, new KeyCombination(Key.F5)), - new KeyboardBinding(UserActions.LoadLayout5, new KeyCombination(Key.F6)), - new KeyboardBinding(UserActions.LoadLayout6, new KeyCombination(Key.F7)), - new KeyboardBinding(UserActions.LoadLayout7, new KeyCombination(Key.F8)), - new KeyboardBinding(UserActions.LoadLayout8, new KeyCombination(Key.F9)), - new KeyboardBinding(UserActions.LoadLayout9, new KeyCombination(Key.F10)), - - new KeyboardBinding(UserActions.SaveLayout0, new KeyCombination(Key.F1, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout1, new KeyCombination(Key.F2, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout2, new KeyCombination(Key.F3, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout3, new KeyCombination(Key.F4, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout4, new KeyCombination(Key.F5, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout5, new KeyCombination(Key.F6, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout6, new KeyCombination(Key.F7, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout7, new KeyCombination(Key.F8, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout8, new KeyCombination(Key.F9, ctrl: true)), - new KeyboardBinding(UserActions.SaveLayout9, new KeyCombination(Key.F10, ctrl: true)), - }; - - public static void InitFrame() + public readonly bool Ctrl; + public readonly bool Alt; + public readonly bool Shift; + public readonly Key Key; + + public override string ToString() { - _anyKeysPressed = ImGui.GetIO().KeysDown.Count > 0; + return (Ctrl ? "Ctrl+" : "") + + (Alt ? "Alt+" : "") + + (Shift ? "Shift+" : "") + + Key; } + } - private static bool _anyKeysPressed; + private KeyboardBinding(UserActions action, KeyCombination combination, bool needsWindowFocus = false, bool keyPressOnly = false) + { + _action = action; + _combination = combination; + _needsWindowFocus = needsWindowFocus; + _keyPressOnly = keyPressOnly; } + + private static readonly List _bindings + = new() + { + // Global + new KeyboardBinding(UserActions.Save, new KeyCombination(Key.S, ctrl: true)), + new KeyboardBinding(UserActions.FocusSelection, new KeyCombination(Key.F)) { _needsWindowHover = true }, + new KeyboardBinding(UserActions.Duplicate, new KeyCombination(Key.D, ctrl: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.DeleteSelection, new KeyCombination(Key.Delete)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.DeleteSelection, new KeyCombination(Key.Backspace)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.CopyToClipboard, new KeyCombination(Key.C, ctrl: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.PasteFromClipboard, new KeyCombination(Key.V, ctrl: true)) { _needsWindowFocus = true }, + + // Playback + new KeyboardBinding(UserActions.PlaybackForward, new KeyCombination(Key.L)), + new KeyboardBinding(UserActions.PlaybackForwardHalfSpeed, new KeyCombination(Key.L, shift: true)), + new KeyboardBinding(UserActions.PlaybackBackwards, new KeyCombination(Key.J)), + new KeyboardBinding(UserActions.PlaybackStop, new KeyCombination(Key.K)), + new KeyboardBinding(UserActions.PlaybackToggle, new KeyCombination(Key.Space)), // TODO: Fixme! + new KeyboardBinding(UserActions.PlaybackPreviousFrame, new KeyCombination(Key.CursorLeft, shift: true)), + new KeyboardBinding(UserActions.PlaybackNextFrame, new KeyCombination(Key.CursorRight, shift: true)), + new KeyboardBinding(UserActions.PlaybackJumpToStartTime, new KeyCombination(Key.Home)), + new KeyboardBinding(UserActions.PlaybackJumpToNextKeyframe, new KeyCombination(Key.Period)), + new KeyboardBinding(UserActions.PlaybackJumpToPreviousKeyframe, new KeyCombination(Key.Comma)), + new KeyboardBinding(UserActions.PlaybackNextFrame, new KeyCombination(Key.CursorRight, shift: true)), + new KeyboardBinding(UserActions.PlaybackJumpBack, new KeyCombination(Key.B)), + + new KeyboardBinding(UserActions.Undo, new KeyCombination(Key.Z, ctrl: true)), + new KeyboardBinding(UserActions.Redo, new KeyCombination(Key.Z, ctrl: true, shift: true)), + + // Timeline + new KeyboardBinding(UserActions.InsertKeyframe, new KeyCombination(Key.C)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.InsertKeyframeWithIncrement, new KeyCombination(Key.C, shift: true)), + new KeyboardBinding(UserActions.ToggleAnimationPinning, new KeyCombination(Key.K, shift: true)), + + new KeyboardBinding(UserActions.TapBeatSync, new KeyCombination(Key.Z)), + new KeyboardBinding(UserActions.TapBeatSyncMeasure, new KeyCombination(Key.X)), + + // Graph window + new KeyboardBinding(UserActions.ToggleDisabled, new KeyCombination(Key.D, shift: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.ToggleBypassed, new KeyCombination(Key.B, shift: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.PinToOutputWindow, new KeyCombination(Key.P)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.DisplayImageAsBackground, new KeyCombination(Key.P, ctrl: true)) { _needsWindowFocus = false }, + new KeyboardBinding(UserActions.ClearBackgroundImage, new KeyCombination(Key.P, ctrl: true, shift: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.LayoutSelection, new KeyCombination(Key.G)), + + new KeyboardBinding(UserActions.AddAnnotation, new KeyCombination(Key.A, shift: true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.AddComment, new KeyCombination(Key.C, shift: true, ctrl:true)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.ToggleVariationsWindow, new KeyCombination(Key.V, alt: true)) { _needsWindowFocus = false }, + new KeyboardBinding(UserActions.SearchGraph, new KeyCombination(Key.F, ctrl: true)) { _needsWindowFocus = false }, + + new KeyboardBinding(UserActions.NavigateBackwards, new KeyCombination(Key.CursorLeft, alt: true)) { _needsWindowFocus = false }, + new KeyboardBinding(UserActions.NavigateForward, new KeyCombination(Key.CursorRight, alt: true)) { _needsWindowFocus = false }, + + new KeyboardBinding(UserActions.SelectToAbove, new KeyCombination(Key.CursorUp)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.SelectToRight, new KeyCombination(Key.CursorRight)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.SelectToBelow, new KeyCombination(Key.CursorDown)) { _needsWindowFocus = true }, + new KeyboardBinding(UserActions.SelectToLeft, new KeyCombination(Key.CursorLeft)) { _needsWindowFocus = true }, + + // Layout and window management + new KeyboardBinding(UserActions.ToggleAllUiElements, new KeyCombination(Key.Esc, shift: true)), + new KeyboardBinding(UserActions.ToggleFullscreen, new KeyCombination(Key.F11)), + new KeyboardBinding(UserActions.ToggleFocusMode, new KeyCombination(Key.F12)), + + new KeyboardBinding(UserActions.LoadBookmark1, new KeyCombination(Key.D1, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark2, new KeyCombination(Key.D2, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark3, new KeyCombination(Key.D3, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark4, new KeyCombination(Key.D4, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark5, new KeyCombination(Key.D5, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark6, new KeyCombination(Key.D6, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark7, new KeyCombination(Key.D7, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark8, new KeyCombination(Key.D8, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark9, new KeyCombination(Key.D9, ctrl: true)), + new KeyboardBinding(UserActions.LoadBookmark0, new KeyCombination(Key.D0, ctrl: true)), + + new KeyboardBinding(UserActions.SaveBookmark1, new KeyCombination(Key.D1, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark2, new KeyCombination(Key.D2, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark3, new KeyCombination(Key.D3, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark4, new KeyCombination(Key.D4, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark5, new KeyCombination(Key.D5, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark6, new KeyCombination(Key.D6, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark7, new KeyCombination(Key.D7, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark8, new KeyCombination(Key.D8, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark9, new KeyCombination(Key.D9, ctrl: true, shift: true)), + new KeyboardBinding(UserActions.SaveBookmark0, new KeyCombination(Key.D0, ctrl: true, shift: true)), + + new KeyboardBinding(UserActions.LoadLayout0, new KeyCombination(Key.F1)), + new KeyboardBinding(UserActions.LoadLayout1, new KeyCombination(Key.F2)), + new KeyboardBinding(UserActions.LoadLayout2, new KeyCombination(Key.F3)), + new KeyboardBinding(UserActions.LoadLayout3, new KeyCombination(Key.F4)), + new KeyboardBinding(UserActions.LoadLayout4, new KeyCombination(Key.F5)), + new KeyboardBinding(UserActions.LoadLayout5, new KeyCombination(Key.F6)), + new KeyboardBinding(UserActions.LoadLayout6, new KeyCombination(Key.F7)), + new KeyboardBinding(UserActions.LoadLayout7, new KeyCombination(Key.F8)), + new KeyboardBinding(UserActions.LoadLayout8, new KeyCombination(Key.F9)), + new KeyboardBinding(UserActions.LoadLayout9, new KeyCombination(Key.F10)), + + new KeyboardBinding(UserActions.SaveLayout0, new KeyCombination(Key.F1, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout1, new KeyCombination(Key.F2, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout2, new KeyCombination(Key.F3, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout3, new KeyCombination(Key.F4, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout4, new KeyCombination(Key.F5, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout5, new KeyCombination(Key.F6, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout6, new KeyCombination(Key.F7, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout7, new KeyCombination(Key.F8, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout8, new KeyCombination(Key.F9, ctrl: true)), + new KeyboardBinding(UserActions.SaveLayout9, new KeyCombination(Key.F10, ctrl: true)), + }; + + private static bool _anyKeysPressed; } \ No newline at end of file diff --git a/Editor/Gui/Interaction/Variations/Model/Variation.cs b/Editor/Gui/Interaction/Variations/Model/Variation.cs index aed1389c0e..e5694957c1 100644 --- a/Editor/Gui/Interaction/Variations/Model/Variation.cs +++ b/Editor/Gui/Interaction/Variations/Model/Variation.cs @@ -95,7 +95,7 @@ public static Variation FromJson(Guid symbolId, JToken jToken) { var inputId = Guid.Parse(inputIdString); var input = symbolForChanges.InputDefinitions.SingleOrDefault(i => i.Id == inputId); - if (input == null) + if (input == null && inputId != Guid.Empty) { Log.Warning($"Can't find symbol input {symbolChildIdString}/{inputId} for preset changes"); continue; diff --git a/Editor/Gui/Interaction/Variations/VariationHandling.cs b/Editor/Gui/Interaction/Variations/VariationHandling.cs index 2db2f421b3..ba81c68501 100644 --- a/Editor/Gui/Interaction/Variations/VariationHandling.cs +++ b/Editor/Gui/Interaction/Variations/VariationHandling.cs @@ -12,6 +12,7 @@ using T3.Editor.Gui.Interaction.Variations.Midi; using T3.Editor.Gui.Interaction.Variations.Model; using T3.Editor.Gui.Windows.Variations; +using T3.Editor.UiModel; //using T3.Gui.Windows.Variations; diff --git a/Editor/Gui/OutputUi/BufferWithViewsOutputUi.cs b/Editor/Gui/OutputUi/BufferWithViewsOutputUi.cs new file mode 100644 index 0000000000..4514be8816 --- /dev/null +++ b/Editor/Gui/OutputUi/BufferWithViewsOutputUi.cs @@ -0,0 +1,55 @@ +using System; +using System.Numerics; +using ImGuiNET; +using T3.Core.DataTypes; +using T3.Core.Operator.Slots; +using T3.Editor.Gui.Styling; + +namespace T3.Editor.Gui.OutputUi +{ + public class BufferWithViewsOutputUi : OutputUi + { + public override IOutputUi Clone() + { + return new BufferWithViewsOutputUi() + { + OutputDefinition = OutputDefinition, + PosOnCanvas = PosOnCanvas, + Size = Size + }; + } + + protected override void DrawTypedValue(ISlot slot) + { + var type = typeof(BufferWithViews); + ImGui.PushFont(Fonts.FontSmall); + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); + ImGui.TextUnformatted(type.Namespace); + ImGui.PopStyleColor(); + ImGui.PopFont(); + + ImGui.TextUnformatted(type.Name); + + if (slot is not Slot bufferSlot + || bufferSlot.Value?.Buffer == null || bufferSlot.Value.Srv == null) + + { + ImGui.TextUnformatted("Undefined"); + return; + } + + try + { + ImGui.Dummy(new Vector2(5,5)); + var elementCount = bufferSlot.Value.Srv.Description.Buffer.ElementCount; + var totalSize = bufferSlot.Value.Buffer.Description.SizeInBytes; + ImGui.TextUnformatted($"{elementCount} × {totalSize/elementCount}"); + ImGui.TextUnformatted($"{totalSize} bytes"); + } + catch (Exception e) + { + ImGui.TextUnformatted("Can't access buffer: " + e.Message); + } + } + } +} \ No newline at end of file diff --git a/Editor/Gui/OutputUi/CommandOutputUi.cs b/Editor/Gui/OutputUi/CommandOutputUi.cs index 8167186a9b..d15b4e5dd4 100644 --- a/Editor/Gui/OutputUi/CommandOutputUi.cs +++ b/Editor/Gui/OutputUi/CommandOutputUi.cs @@ -39,7 +39,7 @@ protected override void Recompute(ISlot slot, EvaluationContext context) var device = ResourceManager.Device; Size2 size = context.RequestedResolution; - var wasRebuild = UpdateTextures(device, size, Format.R16G16B16A16_UNorm); + var wasRebuild = UpdateTextures(device, size, Format.R16G16B16A16_Float); var deviceContext = device.ImmediateContext; var prevViewports = deviceContext.Rasterizer.GetViewports(); var prevTargets = deviceContext.OutputMerger.GetRenderTargets(1); diff --git a/Editor/Gui/OutputUi/DataSetViewCanvas.cs b/Editor/Gui/OutputUi/DataSetViewCanvas.cs index e2d2edec0f..d4fccf5874 100644 --- a/Editor/Gui/OutputUi/DataSetViewCanvas.cs +++ b/Editor/Gui/OutputUi/DataSetViewCanvas.cs @@ -134,7 +134,9 @@ public void Draw(DataSet dataSet) var color = Color.Mix(UiColors.StatusAnimated, UiColors.TextMuted, (float)timeSinceEvent); var pathString = string.Join(" / ", channel.Path); - dl.AddText(layerMin + new Vector2(10,0), color, pathString); + if(!string.IsNullOrEmpty(pathString)) + dl.AddText(layerMin + new Vector2(10,0), color, pathString); + dl.AddLine(new Vector2(layerMin.X, layerMax.Y), layerMax, UiColors.GridLines.Fade(0.4f)); layerMin.Y += layerHeight; diff --git a/Editor/Gui/OutputUi/ValueOutputUi.cs b/Editor/Gui/OutputUi/ValueOutputUi.cs index 6e744bac8d..43107cb596 100644 --- a/Editor/Gui/OutputUi/ValueOutputUi.cs +++ b/Editor/Gui/OutputUi/ValueOutputUi.cs @@ -1,6 +1,8 @@ using System.Diagnostics; +using System.Numerics; using ImGuiNET; using T3.Core.Operator.Slots; +using T3.Editor.Gui.Styling; namespace T3.Editor.Gui.OutputUi { @@ -32,8 +34,22 @@ protected override void DrawTypedValue(ISlot slot) ImGui.EndChild(); break; default: - var t = value?.ToString(); - ImGui.TextUnformatted(t ?? typeof(T).ToString()); + var type = typeof(T); + ImGui.PushFont(Fonts.FontSmall); + + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Fade(0.6f).Rgba); + ImGui.TextUnformatted(type.Namespace); + ImGui.PopStyleColor(); + + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); + ImGui.TextUnformatted(type.Name); + ImGui.PopStyleColor(); + ImGui.PopFont(); + + ImGui.Dummy(new Vector2(0,2 * T3Ui.UiScaleFactor)); + + var valueAsString = value == null ? "undefined" : value.ToString(); + ImGui.TextUnformatted(valueAsString); break; } } diff --git a/Editor/Gui/Selection/CanvasElementSelection.cs b/Editor/Gui/Selection/CanvasElementSelection.cs index a2ff391967..8a8508be48 100644 --- a/Editor/Gui/Selection/CanvasElementSelection.cs +++ b/Editor/Gui/Selection/CanvasElementSelection.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using T3.Core.Logging; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Selection { diff --git a/Editor/Gui/Styling/ColorThemeEditor.cs b/Editor/Gui/Styling/ColorThemeEditor.cs index a858debc77..45beab8a96 100644 --- a/Editor/Gui/Styling/ColorThemeEditor.cs +++ b/Editor/Gui/Styling/ColorThemeEditor.cs @@ -141,7 +141,7 @@ private static void DrawColorEdits(IEnumerable colorFields) } ImGui.SameLine(0, 10); - ImGui.Text(Regex.Replace(f.Name, "(\\B[A-Z])", " $1")); + ImGui.Text(CustomComponents.HumanReadablePascalCase(f.Name)); if (ImGui.IsItemHovered() && ImGui.IsMouseClicked(ImGuiMouseButton.Left)) { FrameStats.Current.UiColorsChanged = true; @@ -168,7 +168,7 @@ private static void DrawColorEdits(IEnumerable colorFields) ImGui.PopID(); } } - + private static void DrawVariations(IEnumerable variationFields) { ImGui.Separator(); diff --git a/Editor/Gui/Styling/CustomComponents.cs b/Editor/Gui/Styling/CustomComponents.cs index 2305bae41b..bd2a9d81fa 100644 --- a/Editor/Gui/Styling/CustomComponents.cs +++ b/Editor/Gui/Styling/CustomComponents.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Reflection; +using System.Text.RegularExpressions; using ImGuiNET; using T3.Core.IO; using T3.Core.Utils; @@ -379,6 +381,7 @@ public static void HelpText(string text) ImGui.TextWrapped(text); ImGui.PopStyleColor(); ImGui.PopFont(); + ImGui.Dummy(new Vector2(0,4 * T3Ui.DisplayScaleFactor)); } /// @@ -432,9 +435,12 @@ public static bool EmptyWindowMessage(string message, string buttonLabel = null) foreach (var line in lines) { - var textSize = ImGui.CalcTextSize(line); - var position = new Vector2(center.X - textSize.X / 2, y); - drawList.AddText(position, emptyMessageColor, line); + if (!string.IsNullOrEmpty(line)) + { + var textSize = ImGui.CalcTextSize(line); + var position = new Vector2(center.X - textSize.X / 2, y); + drawList.AddText(position, emptyMessageColor, line); + } y += textLineHeight; } @@ -457,6 +463,8 @@ public static void TooltipForLastItem(Color color, string message, string additi return; FrameStats.Current.SomethingWithTooltipHovered = true; + if (!useHoverDelay) + _toolTipHoverDelay = 0; if (_toolTipHoverDelay > 0) return; @@ -558,24 +566,28 @@ public static bool DrawIconToggle(string name, Icon icon, ref bool isSelected) return clicked; } - public static bool DrawSearchField(string placeHolderLabel, ref string value, float width = 0) + public static bool DrawInputFieldWithPlaceholder(string placeHolderLabel, ref string value, float width = 0, bool showClear= true, ImGuiInputTextFlags inputFlags= ImGuiInputTextFlags.None) { + var notEmpty = !string.IsNullOrEmpty(value); var wasNull = value == null; if (wasNull) value = string.Empty; - ImGui.SetNextItemWidth(width - FormInputs.ParameterSpacing); - var modified = ImGui.InputText("##" + placeHolderLabel, ref value, 1000); + ImGui.SetNextItemWidth(width - FormInputs.ParameterSpacing - (notEmpty ? ImGui.GetFrameHeight():0)); + var modified = ImGui.InputText("##" + placeHolderLabel, ref value, 1000, inputFlags); if (!modified && wasNull) value = null; - if (!string.IsNullOrEmpty(value)) + if (notEmpty) { - ImGui.SameLine(); - if (ImGui.Button("×")) + if (showClear) { - value = null; - modified = true; + ImGui.SameLine(0,0); + if (ImGui.Button("×" + "##" + placeHolderLabel)) + { + value = null; + modified = true; + } } } else @@ -603,5 +615,10 @@ public static void DrawWindowFocusFrame() var min = ImGui.GetWindowPos() + new Vector2(1,1); ImGui.GetWindowDrawList().AddRect(min, min+ImGui.GetWindowSize() + new Vector2(-2,-1) , UiColors.ForegroundFull.Fade(0.1f)); } + + public static string HumanReadablePascalCase(string f) + { + return Regex.Replace(f, "(\\B[A-Z])", " $1"); + } } } \ No newline at end of file diff --git a/Editor/Gui/Styling/FormInputs.cs b/Editor/Gui/Styling/FormInputs.cs index 38eb92f467..e57d925f46 100644 --- a/Editor/Gui/Styling/FormInputs.cs +++ b/Editor/Gui/Styling/FormInputs.cs @@ -1,535 +1,555 @@ -using System; -using System.Collections.Generic; -using System.Numerics; -using ImGuiNET; -using T3.Editor.Gui.InputUi; -using T3.Editor.Gui.Interaction; -using T3.Editor.Gui.UiHelpers; - -namespace T3.Editor.Gui.Styling -{ - /// - /// A set of custom widgets that allow to quickly draw dialogs with a more "traditional" labels on the left side of input fields. - /// It also provides a bunch of helper methods for minimal layout control. - /// - public static class FormInputs - { - public static void BeginFrame() - { - ResetIndent(); - } - - public static void AddSectionHeader(string label) - { - AddVerticalSpace(10); - ImGui.PushFont(Fonts.FontLarge); - ImGui.Text(label); - ImGui.PopFont(); - } - - public static bool BeginGroup(string label) - { - var shouldBeOpenByDefault = !label.EndsWith("..."); - - AddVerticalSpace(5); - ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); - - var id = ImGui.GetID(label); - if (shouldBeOpenByDefault && !_openedGroups.Contains(id)) - { - ImGui.SetNextItemOpen(true); - _openedGroups.Add(id); - } - - var isOpen = ImGui.TreeNode(label); - ImGui.PushStyleVar(ImGuiStyleVar.IndentSpacing, 0); - ImGui.PopStyleColor(); - return isOpen; - } - - private static HashSet _openedGroups = new(); - - public static void EndGroup() - { - ImGui.PopStyleVar(); - ImGui.TreePop(); - } - - public static bool AddInt(string label, - ref int value, - int min = int.MinValue, - int max = int.MaxValue, - float scale = 1, - string tooltip = null, - int defaultValue = NotADefaultValue) - { - DrawInputLabel(label); - - ImGui.PushID(label); - - var hasReset = defaultValue != NotADefaultValue; - - var size = GetAvailableInputSize(tooltip, hasReset); - var result = SingleValueEdit.Draw(ref value, size, min, max, true, scale); - ImGui.PopID(); - - AppendTooltip(tooltip); - if (AppendResetButton(hasReset, label)) - { - value = defaultValue; - result |= InputEditStateFlags.ModifiedAndFinished; - } - - var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing; - return modified; - } - - private const float DefaultFadeAlpha = 0.7f; - - public static bool AddFloat(string label, - ref float value, - float min = float.NegativeInfinity, - float max = float.PositiveInfinity, - float scale = 0.01f, - bool clamp = false, - string tooltip = null, - float defaultValue = float.NaN) - { - var hasReset = !float.IsNaN(defaultValue); - var isDefault = hasReset && Math.Abs(value - defaultValue) < 0.0001f; - if (isDefault) - { - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha * ImGui.GetStyle().Alpha); - } - - DrawInputLabel(label); - var size = GetAvailableInputSize(tooltip, hasReset); - - ImGui.PushID(label); - var result = SingleValueEdit.Draw(ref value, size, min, max, clamp, scale); - ImGui.PopID(); - - AppendTooltip(tooltip); - if (AppendResetButton(hasReset && !isDefault, label)) - { - value = defaultValue; - result |= InputEditStateFlags.ModifiedAndFinished; - } - - if (isDefault) - { - ImGui.PopStyleVar(); - } - - var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing; - return modified; - } - - public static bool AddEnumDropdown(ref T selectedValue, string label, string tooltip = null) where T : struct, Enum, IConvertible, IFormattable - { - DrawInputLabel(label); - - var inputSize = GetAvailableInputSize(tooltip, false, true); - ImGui.SetNextItemWidth(inputSize.X); - - var names = Enum.GetNames(); - var index = 0; - var selectedIndex = 0; - - foreach (var n in names) - { - if (n == selectedValue.ToString()) - selectedIndex = index; - - index++; - } - - var modified = ImGui.Combo($"##dropDown{typeof(T)}{label}", ref selectedIndex, names, names.Length, names.Length); - if (modified) - { - selectedValue = Enum.GetValues()[selectedIndex]; - } - - AppendTooltip(tooltip); - - return modified; - } - - public static bool AddDropdown(ref string selectedValue, IEnumerable values, string label, string tooltip = null) - { - DrawInputLabel(label); - - var inputSize = GetAvailableInputSize(tooltip, false, true); - ImGui.SetNextItemWidth(inputSize.X); - - var modified = false; - if (ImGui.BeginCombo("##SelectTheme", UserSettings.Config.ColorThemeName, ImGuiComboFlags.HeightLarge)) - { - foreach (var value in values) - { - if (value == null) - continue; - - var isSelected = value == selectedValue; - if (!ImGui.Selectable($"{value}", isSelected, ImGuiSelectableFlags.DontClosePopups)) - continue; - - ImGui.CloseCurrentPopup(); - selectedValue = value; - modified = true; - } - - ImGui.EndCombo(); - } - - AppendTooltip(tooltip); - return modified; - } - - - public static bool AddSegmentedButton(ref T selectedValue, string label) where T : struct, Enum - { - DrawInputLabel(label); - - var modified = false; - var selectedValueString = selectedValue.ToString(); - var isFirst = true; - foreach (var value in Enum.GetValues()) - { - var name = Enum.GetName(value); - if (!isFirst) - { - ImGui.SameLine(); - } - - var isSelected = selectedValueString == value.ToString(); - var clicked = DrawSelectButton(name, isSelected); - - if (clicked) - { - modified = true; - selectedValue = value; - } - - isFirst = false; - } - - return modified; - } - - private static bool DrawSelectButton(string name, bool isSelected) - { - ImGui.PushStyleColor(ImGuiCol.Button, isSelected ? UiColors.BackgroundActive.Rgba : UiColors.BackgroundButton.Rgba); - ImGui.PushStyleColor(ImGuiCol.ButtonHovered, isSelected ? UiColors.BackgroundActive.Rgba : UiColors.BackgroundButton.Rgba); - ImGui.PushStyleColor(ImGuiCol.Text, isSelected ? UiColors.BackgroundFull.Rgba : UiColors.ForegroundFull.Rgba); - ImGui.PushStyleColor(ImGuiCol.ButtonActive, UiColors.BackgroundActive.Rgba); - - var clicked = ImGui.Button(name); - ImGui.PopStyleColor(4); - return clicked; - } - - private const string NoDefaultString = "_"; - - /// - /// Draws string input or file picker. - /// - public static bool AddStringInput(string label, - ref string value, - string placeHolder = null, - string warning = null, - string tooltip = null, - string defaultValue = NoDefaultString) - { - var hasDefault = defaultValue != NoDefaultString; - var isDefault = hasDefault && value == defaultValue; - - if (isDefault) - { - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha); - } - - DrawInputLabel(label); - var wasNull = value == null; - if (wasNull) - value = string.Empty; - - var inputSize = GetAvailableInputSize(tooltip, false, true); - ImGui.SetNextItemWidth(inputSize.X); - var modified = ImGui.InputText("##" + label, ref value, 1000); - if (!modified && wasNull) - value = null; - - AppendTooltip(tooltip); - - if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(placeHolder)) - { - var drawList = ImGui.GetWindowDrawList(); - var minPos = ImGui.GetItemRectMin(); - var maxPos = ImGui.GetItemRectMax(); - drawList.PushClipRect(minPos, maxPos); - drawList.AddText(minPos + new Vector2(8, 3), UiColors.ForegroundFull.Fade(0.25f), placeHolder); - drawList.PopClipRect(); - } - - if (isDefault) - { - ImGui.PopStyleVar(); - } - - if (AppendResetButton(hasDefault && !isDefault, label)) - { - value = defaultValue; - modified = true; - } - - DrawWarningBelowField(warning); - - return modified; - } - - /// - /// Draws string input or file picker. - /// - public static bool AddFilePicker(string label, - ref string value, - string placeHolder = null, - string warning = null, - FileOperations.FilePickerTypes showFilePicker = FileOperations.FilePickerTypes.None) - { - DrawInputLabel(label); - - var isFilePickerVisible = showFilePicker != FileOperations.FilePickerTypes.None; - float spaceForFilePicker = isFilePickerVisible ? 30 : 0; - var inputSize = GetAvailableInputSize(null, false, true, spaceForFilePicker); - ImGui.SetNextItemWidth(inputSize.X); - - var wasNull = value == null; - if (wasNull) - value = string.Empty; - - var modified = ImGui.InputText("##" + label, ref value, 1000); - if (!modified && wasNull) - value = null; - - if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(placeHolder)) - { - var drawList = ImGui.GetWindowDrawList(); - var minPos = ImGui.GetItemRectMin(); - var maxPos = ImGui.GetItemRectMax(); - drawList.PushClipRect(minPos, maxPos); - drawList.AddText(minPos + new Vector2(8, 3), UiColors.ForegroundFull.Fade(0.25f), placeHolder); - drawList.PopClipRect(); - } - - if (isFilePickerVisible) - { - modified |= FileOperations.DrawFileSelector(showFilePicker, ref value); - } - - DrawWarningBelowField(warning); - return modified; - } - - public static bool AddCheckBox(string label, - ref bool value, - string tooltip = null, - bool? defaultValue = null) - { - var hasDefault = defaultValue != null; - var isDefault = hasDefault && value == (bool)defaultValue; - - if (isDefault) - { - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha); - } - - ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding, 0) + 20); - var modified = ImGui.Checkbox(label, ref value); - - AppendTooltip(tooltip); - if (isDefault) - { - ImGui.PopStyleVar(); - } - - if (AppendResetButton(hasDefault && !isDefault, label)) - { - value = defaultValue ?? false; - modified = true; - } - - return modified; - } - - - - - - public static void AddHint(string label) - { - if (string.IsNullOrEmpty(label)) - return; - - AddVerticalSpace(5); - ApplyIndent(); - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f); - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(10, 20)); - - AddIcon(Icon.Hint); - - ImGui.SameLine(); - ImGui.TextWrapped(label); - ImGui.Indent(-13); - ImGui.PopStyleVar(2); - } - - public static void AddVerticalSpace(float size = 10) - { - ImGui.Dummy(new Vector2(1, size * T3Ui.UiScaleFactor)); - } - - #region layout helpers - public static void SetIndent(float newIndent) - { - _paramIndent = newIndent; - } - - public static void ResetIndent() - { - _paramIndent = DefaultParameterIndent; - } - - public static void ApplyIndent() - { - ImGui.SetCursorPosX(LeftParameterPadding + ParameterSpacing); - } - - public static void SetWidth(float ratio) - { - _widthRatio = ratio; - } - - public static void ResetWidth() - { - _widthRatio = 1; - } - - public static void DrawInputLabel(string label) - { - if (string.IsNullOrEmpty(label)) - return; - - var labelSize = ImGui.CalcTextSize(label); - var p = ImGui.GetCursorPos(); - ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding - labelSize.X, 0) + 10); - ImGui.AlignTextToFramePadding(); - - ImGui.TextUnformatted(label); - ImGui.SetCursorPos(p); - - ImGui.SameLine(); - ImGui.SetCursorPosX(LeftParameterPadding + ParameterSpacing); - } - - private static void DrawWarningBelowField(string warning) - { - if (string.IsNullOrEmpty(warning)) - return; - - ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding, 0) + 10); - ImGui.PushFont(Fonts.FontSmall); - ImGui.PushStyleColor(ImGuiCol.Text, UiColors.StatusError.Rgba); - ImGui.TextUnformatted(warning); - ImGui.PopStyleColor(); - ImGui.PopFont(); - } - #endregion - - #region internal helpers - private static Vector2 GetAvailableInputSize(string tooltip, bool hasReset, bool fillWidth = false, float rightPadding = 0) - { - var toolWidth = 20f * T3Ui.UiScaleFactor; - var sizeForResetToDefault = hasReset ? toolWidth : 0; - var sizeForTooltip = !string.IsNullOrEmpty(tooltip) ? toolWidth : 0; - - var availableWidth = fillWidth ? ImGui.GetContentRegionAvail().X * _widthRatio : 200; - - var vector2 = new Vector2(availableWidth - - 20 - - rightPadding - - sizeForResetToDefault - - sizeForTooltip, - ImGui.GetFrameHeight()); - return vector2; - } - - private static void AppendTooltip(string tooltip) - { - if (string.IsNullOrEmpty(tooltip)) - return; - - ImGui.SameLine(); - - ImGui.PushFont(Icons.IconFont); - ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.5f, 0.5f)); - ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); - - ImGui.AlignTextToFramePadding(); - ImGui.TextUnformatted(" " + (char)Icon.Help); - - ImGui.PopStyleVar(2); - ImGui.PopFont(); - - //CustomComponents.TooltipForLastItem(tooltip, null, false); - if (!ImGui.IsItemHovered()) - return; - - // Tooltip - ImGui.PushStyleColor(ImGuiCol.PopupBg, UiColors.BackgroundFull.Rgba); - ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1); - ImGui.BeginTooltip(); - ImGui.PushTextWrapPos(300); - ImGui.TextUnformatted(tooltip); - ImGui.PopTextWrapPos(); - ImGui.EndTooltip(); - ImGui.PopStyleColor(); - ImGui.PopStyleVar(1); - } - - private static bool AppendResetButton(bool hasReset, string id) - { - if (!hasReset) - return false; - - ImGui.SameLine(); - ImGui.PushID(id); - var clicked = CustomComponents.IconButton(Icon.Revert, Vector2.One * ImGui.GetFrameHeight()); - ImGui.PopID(); - return clicked; - } - - private static void AddIcon(Icon icon) - { - ImGui.PushFont(Icons.IconFont); - ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.5f, 0.5f)); - ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); - - ImGui.TextUnformatted("" + (char)(icon)); - - ImGui.PopFont(); - ImGui.PopStyleVar(2); - } - #endregion - - private const int NotADefaultValue = Int32.MinValue; - - private const float DefaultParameterIndent = 170; - private static float _paramIndent = DefaultParameterIndent; - private static float _widthRatio = 1; - private static float LeftParameterPadding => _paramIndent * T3Ui.UiScaleFactor; - public static float ParameterSpacing => 20 * T3Ui.UiScaleFactor; - - - } +using System; +using System.Collections.Generic; +using System.Numerics; +using ImGuiNET; +using T3.Editor.Gui.InputUi; +using T3.Editor.Gui.Interaction; +using T3.Editor.Gui.UiHelpers; + +namespace T3.Editor.Gui.Styling +{ + /// + /// A set of custom widgets that allow to quickly draw dialogs with a more "traditional" labels on the left side of input fields. + /// It also provides a bunch of helper methods for minimal layout control. + /// + public static class FormInputs + { + public static void BeginFrame() + { + SetIndentToParameters(); + } + + public static void AddSectionHeader(string label) + { + AddVerticalSpace(1); + ImGui.PushFont(Fonts.FontLarge); + ImGui.Text(label); + ImGui.PopFont(); + //AddVerticalSpace(20); + + } + + public static bool BeginGroup(string label) + { + var shouldBeOpenByDefault = !label.EndsWith("..."); + + AddVerticalSpace(5); + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); + + var id = ImGui.GetID(label); + if (shouldBeOpenByDefault && !_openedGroups.Contains(id)) + { + ImGui.SetNextItemOpen(true); + _openedGroups.Add(id); + } + + var isOpen = ImGui.TreeNode(label); + ImGui.PopStyleColor(); + if(isOpen) + ImGui.PushStyleVar(ImGuiStyleVar.IndentSpacing, 0); + + return isOpen; + } + + private static HashSet _openedGroups = new(); + + public static void EndGroup() + { + ImGui.PopStyleVar(); + ImGui.TreePop(); + } + + public static bool AddInt(string label, + ref int value, + int min = int.MinValue, + int max = int.MaxValue, + float scale = 1, + string tooltip = null, + int defaultValue = NotADefaultValue) + { + DrawInputLabel(label); + + ImGui.PushID(label); + + var hasReset = defaultValue != NotADefaultValue; + + var size = GetAvailableInputSize(tooltip, hasReset); + var result = SingleValueEdit.Draw(ref value, size, min, max, true, scale); + ImGui.PopID(); + + AppendTooltip(tooltip); + if (AppendResetButton(hasReset, label)) + { + value = defaultValue; + result |= InputEditStateFlags.ModifiedAndFinished; + } + + var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing; + return modified; + } + + private const float DefaultFadeAlpha = 0.7f; + + public static bool AddFloat(string label, + ref float value, + float min = float.NegativeInfinity, + float max = float.PositiveInfinity, + float scale = 0.01f, + bool clamp = false, + string tooltip = null, + float defaultValue = float.NaN) + { + var hasReset = !float.IsNaN(defaultValue); + var isDefault = hasReset && Math.Abs(value - defaultValue) < 0.0001f; + if (isDefault) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha * ImGui.GetStyle().Alpha); + } + + DrawInputLabel(label); + var size = GetAvailableInputSize(tooltip, hasReset); + + ImGui.PushID(label); + var result = SingleValueEdit.Draw(ref value, size, min, max, clamp, scale); + ImGui.PopID(); + + AppendTooltip(tooltip); + if (AppendResetButton(hasReset && !isDefault, label)) + { + value = defaultValue; + result |= InputEditStateFlags.ModifiedAndFinished; + } + + if (isDefault) + { + ImGui.PopStyleVar(); + } + + var modified = (result & InputEditStateFlags.Modified) != InputEditStateFlags.Nothing; + return modified; + } + + public static bool AddEnumDropdown(ref T selectedValue, string label, string tooltip = null) where T : struct, Enum, IConvertible, IFormattable + { + DrawInputLabel(label); + + var inputSize = GetAvailableInputSize(tooltip, false, true); + ImGui.SetNextItemWidth(inputSize.X); + + var modified = DrawEnumDropdown(ref selectedValue, label); + + AppendTooltip(tooltip); + + return modified; + } + + public static bool DrawEnumDropdown(ref T selectedValue, string label) where T : struct, Enum, IConvertible, IFormattable + { + var names = Enum.GetNames(); + var index = 0; + var selectedIndex = 0; + + foreach (var n in names) + { + if (n == selectedValue.ToString()) + { + selectedIndex = index; + break; + } + + index++; + } + + var modified = ImGui.Combo($"##dropDown{typeof(T)}{label}", ref selectedIndex, names, names.Length, names.Length); + if (modified) + { + selectedValue = Enum.GetValues()[selectedIndex]; + } + + return modified; + } + + + public static bool AddDropdown(ref string selectedValue, IEnumerable values, string label, string tooltip = null) + { + DrawInputLabel(label); + + var inputSize = GetAvailableInputSize(tooltip, false, true); + ImGui.SetNextItemWidth(inputSize.X); + + var modified = false; + if (ImGui.BeginCombo("##SelectTheme", UserSettings.Config.ColorThemeName, ImGuiComboFlags.HeightLarge)) + { + foreach (var value in values) + { + if (value == null) + continue; + + var isSelected = value == selectedValue; + if (!ImGui.Selectable($"{value}", isSelected, ImGuiSelectableFlags.DontClosePopups)) + continue; + + ImGui.CloseCurrentPopup(); + selectedValue = value; + modified = true; + } + + ImGui.EndCombo(); + } + + AppendTooltip(tooltip); + return modified; + } + + + public static bool AddSegmentedButton(ref T selectedValue, string label, float columnWidth=0) where T : struct, Enum + { + DrawInputLabel(label); + + var modified = false; + var selectedValueString = selectedValue.ToString(); + var isFirst = true; + + foreach (var value in Enum.GetValues()) + { + var name = CustomComponents.HumanReadablePascalCase(Enum.GetName(value)); + if (!isFirst && columnWidth <=0) + { + ImGui.SameLine(); + } + + var isSelected = selectedValueString == value.ToString(); + var clicked = DrawSelectButton(name, isSelected, columnWidth); + + if (clicked) + { + modified = true; + selectedValue = value; + } + + isFirst = false; + } + + return modified; + } + + private static bool DrawSelectButton(string name, bool isSelected, float width = 0) + { + ImGui.PushStyleColor(ImGuiCol.Button, isSelected ? UiColors.BackgroundActive.Rgba : UiColors.BackgroundButton.Rgba); + ImGui.PushStyleColor(ImGuiCol.ButtonHovered, isSelected ? UiColors.BackgroundActive.Rgba : UiColors.BackgroundButton.Rgba); + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.ForegroundFull.Rgba); + ImGui.PushStyleColor(ImGuiCol.ButtonActive, UiColors.BackgroundActive.Fade(0.7f).Rgba); + + var clicked = ImGui.Button(name, new Vector2(width,0)); + ImGui.PopStyleColor(4); + return clicked; + } + + private const string NoDefaultString = "_"; + + /// + /// Draws string input or file picker. + /// + public static bool AddStringInput(string label, + ref string value, + string placeHolder = null, + string warning = null, + string tooltip = null, + string defaultValue = NoDefaultString) + { + var hasDefault = defaultValue != NoDefaultString; + var isDefault = hasDefault && value == defaultValue; + + if (isDefault) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha); + } + + DrawInputLabel(label); + var wasNull = value == null; + if (wasNull) + value = string.Empty; + + var inputSize = GetAvailableInputSize(tooltip, false, true); + ImGui.SetNextItemWidth(inputSize.X); + var modified = ImGui.InputText("##" + label, ref value, 1000); + if (!modified && wasNull) + value = null; + + AppendTooltip(tooltip); + + if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(placeHolder)) + { + var drawList = ImGui.GetWindowDrawList(); + var minPos = ImGui.GetItemRectMin(); + var maxPos = ImGui.GetItemRectMax(); + drawList.PushClipRect(minPos, maxPos); + drawList.AddText(minPos + new Vector2(8, 3), UiColors.ForegroundFull.Fade(0.25f), placeHolder); + drawList.PopClipRect(); + } + + if (isDefault) + { + ImGui.PopStyleVar(); + } + + if (AppendResetButton(hasDefault && !isDefault, label)) + { + value = defaultValue; + modified = true; + } + + DrawWarningBelowField(warning); + + return modified; + } + + /// + /// Draws string input or file picker. + /// + public static bool AddFilePicker(string label, + ref string value, + string placeHolder = null, + string warning = null, + FileOperations.FilePickerTypes showFilePicker = FileOperations.FilePickerTypes.None) + { + DrawInputLabel(label); + + var isFilePickerVisible = showFilePicker != FileOperations.FilePickerTypes.None; + float spaceForFilePicker = isFilePickerVisible ? 30 : 0; + var inputSize = GetAvailableInputSize(null, false, true, spaceForFilePicker); + ImGui.SetNextItemWidth(inputSize.X); + + var wasNull = value == null; + if (wasNull) + value = string.Empty; + + var modified = ImGui.InputText("##" + label, ref value, 1000); + if (!modified && wasNull) + value = null; + + if (string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(placeHolder)) + { + var drawList = ImGui.GetWindowDrawList(); + var minPos = ImGui.GetItemRectMin(); + var maxPos = ImGui.GetItemRectMax(); + drawList.PushClipRect(minPos, maxPos); + drawList.AddText(minPos + new Vector2(8, 3), UiColors.ForegroundFull.Fade(0.25f), placeHolder); + drawList.PopClipRect(); + } + + if (isFilePickerVisible) + { + modified |= FileOperations.DrawFileSelector(showFilePicker, ref value); + } + + DrawWarningBelowField(warning); + return modified; + } + + public static bool AddCheckBox(string label, + ref bool value, + string tooltip = null, + bool? defaultValue = null) + { + var hasDefault = defaultValue != null; + var isDefault = hasDefault && value == (bool)defaultValue; + + if (isDefault) + { + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, DefaultFadeAlpha); + } + + ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding, 0) + 20); + var modified = ImGui.Checkbox(label, ref value); + + AppendTooltip(tooltip); + if (isDefault) + { + ImGui.PopStyleVar(); + } + + if (AppendResetButton(hasDefault && !isDefault, label)) + { + value = defaultValue ?? false; + modified = true; + } + + return modified; + } + + + + public static void AddHint(string label) + { + if (string.IsNullOrEmpty(label)) + return; + + AddVerticalSpace(5); + ApplyIndent(); + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 0.5f); + ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(10, 20)); + + AddIcon(Icon.Hint); + + ImGui.SameLine(); + ImGui.TextWrapped(label); + //ImGui.Indent(-13); + ImGui.PopStyleVar(2); + } + + public static void AddVerticalSpace(float size = 20) + { + ImGui.Dummy(new Vector2(1, size * T3Ui.UiScaleFactor)); + } + + #region layout helpers + public static void SetIndent(float newIndent) + { + _paramIndent = newIndent; + } + + public static void SetIndentToLeft() + { + _paramIndent = 0; + } + + + public static void SetIndentToParameters() + { + _paramIndent = DefaultParameterIndent; + } + + public static void ApplyIndent() + { + ImGui.SetCursorPosX(LeftParameterPadding + ParameterSpacing); + } + + public static void SetWidth(float ratio) + { + _widthRatio = ratio; + } + + public static void ResetWidth() + { + _widthRatio = 1; + } + + public static void DrawInputLabel(string label) + { + if (string.IsNullOrEmpty(label)) + return; + + var labelSize = ImGui.CalcTextSize(label); + var p = ImGui.GetCursorPos(); + ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding - labelSize.X, 0) + 10); + ImGui.AlignTextToFramePadding(); + + ImGui.TextUnformatted(label); + ImGui.SetCursorPos(p); + + ImGui.SameLine(); + ImGui.SetCursorPosX(LeftParameterPadding + ParameterSpacing); + } + + private static void DrawWarningBelowField(string warning) + { + if (string.IsNullOrEmpty(warning)) + return; + + ImGui.SetCursorPosX(MathF.Max(LeftParameterPadding, 0) + 20); + ImGui.PushFont(Fonts.FontSmall); + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.StatusError.Rgba); + ImGui.TextUnformatted(warning); + ImGui.PopStyleColor(); + ImGui.PopFont(); + } + #endregion + + #region internal helpers + private static Vector2 GetAvailableInputSize(string tooltip, bool hasReset, bool fillWidth = false, float rightPadding = 0) + { + var toolWidth = 20f * T3Ui.UiScaleFactor; + var sizeForResetToDefault = hasReset ? toolWidth : 0; + var sizeForTooltip = !string.IsNullOrEmpty(tooltip) ? toolWidth : 0; + + var availableWidth = fillWidth ? ImGui.GetContentRegionAvail().X * _widthRatio : 200; + + var vector2 = new Vector2(availableWidth + - 20 + - rightPadding + - sizeForResetToDefault + - sizeForTooltip, + ImGui.GetFrameHeight()); + return vector2; + } + + private static void AppendTooltip(string tooltip) + { + if (string.IsNullOrEmpty(tooltip)) + return; + + ImGui.SameLine(); + + ImGui.PushFont(Icons.IconFont); + ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.5f, 0.5f)); + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); + + ImGui.AlignTextToFramePadding(); + ImGui.TextUnformatted(" " + (char)Icon.Help); + + ImGui.PopStyleVar(2); + ImGui.PopFont(); + + //CustomComponents.TooltipForLastItem(tooltip, null, false); + if (!ImGui.IsItemHovered()) + return; + + // Tooltip + ImGui.PushStyleColor(ImGuiCol.PopupBg, UiColors.BackgroundFull.Rgba); + ImGui.PushStyleVar(ImGuiStyleVar.Alpha, 1); + ImGui.BeginTooltip(); + ImGui.PushTextWrapPos(300); + ImGui.TextUnformatted(tooltip); + ImGui.PopTextWrapPos(); + ImGui.EndTooltip(); + ImGui.PopStyleColor(); + ImGui.PopStyleVar(1); + } + + private static bool AppendResetButton(bool hasReset, string id) + { + if (!hasReset) + return false; + + ImGui.SameLine(); + ImGui.PushID(id); + var clicked = CustomComponents.IconButton(Icon.Revert, Vector2.One * ImGui.GetFrameHeight()); + ImGui.PopID(); + return clicked; + } + + private static void AddIcon(Icon icon) + { + ImGui.PushFont(Icons.IconFont); + ImGui.PushStyleVar(ImGuiStyleVar.ButtonTextAlign, new Vector2(0.5f, 0.5f)); + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero); + + ImGui.TextUnformatted("" + (char)(icon)); + + ImGui.PopFont(); + ImGui.PopStyleVar(2); + } + #endregion + + private const int NotADefaultValue = Int32.MinValue; + + private const float DefaultParameterIndent = 170; + private static float _paramIndent = DefaultParameterIndent; + private static float _widthRatio = 1; + private static float LeftParameterPadding => _paramIndent * T3Ui.UiScaleFactor; + public static float ParameterSpacing => 20 * T3Ui.UiScaleFactor; + + + } } \ No newline at end of file diff --git a/Editor/Gui/Styling/Icons.cs b/Editor/Gui/Styling/Icons.cs index ef51738aad..bc2a6d240c 100644 --- a/Editor/Gui/Styling/Icons.cs +++ b/Editor/Gui/Styling/Icons.cs @@ -8,11 +8,11 @@ namespace T3.Editor.Gui.Styling /// /// Handles the mapping of custom icons /// - static class Icons + internal static class Icons { public static ImFontPtr IconFont { get; set; } - public static void Draw(Icon icon) + private static void Draw(Icon icon) { ImGui.PushFont(IconFont); ImGui.TextUnformatted(((char)(int)icon).ToString()); @@ -80,12 +80,12 @@ public static void DrawIconAtScreenPosition(Icon icon, color); } - public static void DrawIconOnLastItem(Icon icon, Color color) + public static void DrawIconOnLastItem(Icon icon, Color color, float alignment= 0.5f) { var pos = ImGui.GetItemRectMin(); var size = ImGui.GetItemRectMax() - pos; GetGlyphDefinition(icon, out var uvRange, out var iconSize); - var centerOffset = MathUtils.Floor((size - iconSize)/2); + var centerOffset = MathUtils.Floor( (size - iconSize) * new Vector2( alignment, 0.5f)); var alignedPos = pos + centerOffset; ImGui.GetWindowDrawList().AddImage(ImGui.GetIO().Fonts.TexID, alignedPos, @@ -165,6 +165,7 @@ public IconSource(Icon icon, Vector2 pos, Vector2 size) public static readonly IconSource[] CustomIcons = { + new (Icon.None, 0), new (Icon.DopeSheetKeyframeLinearSelected, 0, new Vector2(15, 25)), new (Icon.DopeSheetKeyframeLinear, 1, new Vector2(15, 25)), new (Icon.LastKeyframe, 2, new Vector2(15, 25)), @@ -226,7 +227,7 @@ public IconSource(Icon icon, Vector2 pos, Vector2 size) new (Icon.Plus, 54), new (Icon.HoverScrub, 55), new (Icon.AutoRefresh, 56), - new (Icon.Camera, 57), + new (Icon.Snapshot, 57), new (Icon.Move, 58), new (Icon.Scale, 59), new (Icon.Rotate, 60), @@ -245,7 +246,10 @@ public IconSource(Icon icon, Vector2 pos, Vector2 size) new (Icon.AddOpToInput, 73), new (Icon.ExtractInput, 74), new (Icon.IO, 75), - new (Icon.None, 75), + new (Icon.Flame, 76), + new (Icon.Comment, 77), + new (Icon.Camera, 78), + new (Icon.PopUp, slotIndex:79), }; public const string IconAtlasPath = @"Resources\t3-editor\images\t3-icons.png"; @@ -310,7 +314,7 @@ public enum Icon Plus, HoverScrub, AutoRefresh, - Camera, + Snapshot, Move, Scale, Rotate, @@ -328,7 +332,10 @@ public enum Icon AddKeyframe, AddOpToInput, ExtractInput, + Flame, IO, - + Comment, + Camera, + PopUp } } \ No newline at end of file diff --git a/Editor/Gui/Styling/InputWithTypeAheadSearch.cs b/Editor/Gui/Styling/InputWithTypeAheadSearch.cs index 4e7ba2def6..7d76ec6295 100644 --- a/Editor/Gui/Styling/InputWithTypeAheadSearch.cs +++ b/Editor/Gui/Styling/InputWithTypeAheadSearch.cs @@ -7,10 +7,21 @@ namespace T3.Editor.Gui.Styling { + /// + /// Draws a type ahead input + /// + /// + /// Sadly, the implementation of this component is a single horrible hack. + /// It's probably the single most ugly peace of ImGui code in the whole codebase. + /// also see: + /// https://github.com/ocornut/imgui/issues/718 + /// https://github.com/ocornut/imgui/issues/3725 + /// + /// It should work for now, but it's likely to break with future versions of ImGui. + /// public static class InputWithTypeAheadSearch { - public static bool Draw(string label, ref string filter, IEnumerable items) { var inputId = ImGui.GetID(label); @@ -59,23 +70,23 @@ public static bool Draw(string label, ref string filter, IEnumerable ite ImGui.SetNextWindowPos(new Vector2(ImGui.GetItemRectMin().X, ImGui.GetItemRectMax().Y)); ImGui.SetNextWindowSize(new Vector2(ImGui.GetItemRectSize().X, 320)); + if (ImGui.IsItemFocused() && ImGui.IsKeyPressed((ImGuiKey)Key.Return)) + { + wasChanged = true; + _activeInputId = 0; + } if (ImGui.Begin("##typeAheadSearchPopup", ref isSearchResultWindowOpen, ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoMove - | ImGuiWindowFlags.Popup + | ImGuiWindowFlags.Tooltip // ugly as f**k. Sadly .PopUp will lead to random crashes. + | ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.ChildWindow )) { _lastTypeAheadResults.Clear(); var index = 0; ImGui.PushStyleColor(ImGuiCol.ButtonHovered, UiColors.Gray.Rgba); - - if (ImGui.IsMouseClicked(ImGuiMouseButton.Left) && !ImGui.IsWindowHovered(ImGuiHoveredFlags.RectOnly)) - { - _activeInputId = 0; - ImGui.CloseCurrentPopup(); - } foreach (var word in items) { @@ -83,11 +94,16 @@ public static bool Draw(string label, ref string filter, IEnumerable ite continue; var isSelected = index == _selectedResultIndex; + + // We can't use IsItemHovered because we need to use Tooltip hack ImGui.PushStyleColor(ImGuiCol.Text, UiColors.Text.Rgba); ImGui.Selectable(word, isSelected); ImGui.PopStyleColor(); + + var isItemHovered = new ImRect(ImGui.GetItemRectMin(), ImGui.GetItemRectMax()).Contains( ImGui.GetMousePos()); - if (ImGui.IsItemClicked() || (isSelected && ImGui.IsKeyPressed((ImGuiKey)Key.Return))) + if ((ImGui.IsMouseClicked(ImGuiMouseButton.Left) && isItemHovered) + || (isSelected && ImGui.IsKeyPressed((ImGuiKey)Key.Return))) { filter = word; wasChanged = true; @@ -98,6 +114,13 @@ public static bool Draw(string label, ref string filter, IEnumerable ite if (++index > 100) break; } + + var isPopupHovered = new ImRect(ImGui.GetWindowContentRegionMin(), ImGui.GetWindowContentRegionMax()).Contains(ImGui.GetMousePos()); + + if (!isPopupHovered && ImGui.IsMouseClicked(ImGuiMouseButton.Left)) + { + _activeInputId = 0; + } ImGui.PopStyleColor(); } diff --git a/Editor/Gui/T3RenderForm.cs b/Editor/Gui/T3RenderForm.cs deleted file mode 100644 index f42a96bdd0..0000000000 --- a/Editor/Gui/T3RenderForm.cs +++ /dev/null @@ -1,546 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Windows.Forms; -using ImGuiNET; -using SharpDX; -using SharpDX.D3DCompiler; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using SharpDX.Mathematics.Interop; -using SharpDX.WIC; -using T3.Core.Logging; -using T3.Editor.Gui.Styling; -using T3.Editor.SystemUi; -using T3.SystemUi; -using Buffer = SharpDX.Direct3D11.Buffer; -using Device = SharpDX.Direct3D11.Device; -using Vector2 = System.Numerics.Vector2; - -namespace T3.Editor.Gui -{ - /// - /// Binds ImGui to a SharpDX render form - /// - public class T3RenderForm : IRenderGui - { - //public Device Device => _device; - private Device _device; - private DeviceContext _deviceContext; - private Buffer _vb; - private Buffer _ib; - private ShaderBytecode _vertexShaderBlob; - private VertexShader _vertexShader; - private InputLayout _inputLayout; - private Buffer _vertexConstantBuffer; - private ShaderBytecode _pixelShaderBlob; - private PixelShader _pixelShader; - private SamplerState _fontSampler; - private ShaderResourceView _fontTextureView; - private RasterizerState _rasterizerState; - private BlendState _blendState; - private DepthStencilState _depthStencilState; - private int _vertexBufferSize = 5000, _indexBufferSize = 1000; - private readonly Dictionary _srvCache = new Dictionary(); - - private int _windowWidth; - private int _windowHeight; - - private readonly Vector2 _scaleFactor = Vector2.One; - - public void Initialize(Device device, int width, int height) - { - if (device == null) - { - Log.Error("Can't initialize window without device."); - EditorUi.Instance.ShowMessageBox("Can't initialize rendering device.","Graphics error"); - EditorUi.Instance.ExitApplication(); - } - _device = device; - _deviceContext = device.ImmediateContext; - _windowWidth = width; - _windowHeight = height; - - IntPtr context = ImGui.CreateContext(); - ImGui.SetCurrentContext(context); - - SetKeyMappings(); - - SetPerFrameImGuiData(1f / 60f); - - ImGui.GetIO().BackendFlags |= ImGuiBackendFlags.HasMouseCursors; - ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.DockingEnable; - //ImGui.GetIO().ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; - } - - public void RenderDrawData(ImDrawDataPtr drawData) - { - if (_vb == null || _vertexBufferSize < drawData.TotalVtxCount) - { - DisposeObj(ref _vb); - _vertexBufferSize = drawData.TotalVtxCount + 5000; - _vb = new Buffer(_device, - new BufferDescription() - { - SizeInBytes = _vertexBufferSize * Unsafe.SizeOf(), - Usage = ResourceUsage.Dynamic, - BindFlags = BindFlags.VertexBuffer, - CpuAccessFlags = CpuAccessFlags.Write - }); - } - - if (_ib == null || _indexBufferSize < drawData.TotalIdxCount) - { - DisposeObj(ref _ib); - _indexBufferSize = drawData.TotalIdxCount + 10000; - _ib = new Buffer(_device, - new BufferDescription() - { - SizeInBytes = _indexBufferSize * Unsafe.SizeOf(), - Usage = ResourceUsage.Dynamic, - BindFlags = BindFlags.IndexBuffer, - CpuAccessFlags = CpuAccessFlags.Write - }); - } - - // Copy and convert all vertices into a single contiguous buffer - _deviceContext.MapSubresource(_vb, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out var vbStream); - _deviceContext.MapSubresource(_ib, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out var ibStream); - for (int n = 0; n < drawData.CmdListsCount; n++) - { - ImDrawListPtr cmdList = drawData.CmdListsRange[n]; - vbStream.WriteRange(cmdList.VtxBuffer.Data, (uint)(cmdList.VtxBuffer.Size * Unsafe.SizeOf())); - ibStream.WriteRange(cmdList.IdxBuffer.Data, (uint)(cmdList.IdxBuffer.Size * Unsafe.SizeOf())); - } - - vbStream.Dispose(); - ibStream.Dispose(); - _deviceContext.UnmapSubresource(_vb, 0); - _deviceContext.UnmapSubresource(_ib, 0); - - // Setup orthographic projection matrix into our constant buffer - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). - var imGuiIO = ImGui.GetIO(); - var projectionMatrix = Matrix4x4.CreateOrthographicOffCenter(0.0f, imGuiIO.DisplaySize.X, imGuiIO.DisplaySize.Y, 0.0f, -1.0f, 1.0f); - _deviceContext.MapSubresource(_vertexConstantBuffer, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out var cbStream); - cbStream.Write(projectionMatrix); - cbStream.Dispose(); - _deviceContext.UnmapSubresource(_vertexConstantBuffer, 0); - - // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) - var prevScissorRects = new RawRectangle[16]; - _deviceContext.Rasterizer.GetScissorRectangles(prevScissorRects); - var prevViewports = _deviceContext.Rasterizer.GetViewports(); - var prevRasterizerState = _deviceContext.Rasterizer.State; - var prevBlendState = _deviceContext.OutputMerger.BlendState; - var prevBlendFactor = _deviceContext.OutputMerger.BlendFactor; - var prevSampleMask = _deviceContext.OutputMerger.BlendSampleMask; - var prevDepthStencilState = _deviceContext.OutputMerger.DepthStencilState; - var prevStencilRef = _deviceContext.OutputMerger.DepthStencilReference; - var prevPsShaderResource = _deviceContext.PixelShader.GetShaderResources(0, 1)[0]; - var prevPsSampler = _deviceContext.PixelShader.GetSamplers(0, 1); - var prevPs = _deviceContext.PixelShader.Get(); - var prevVs = _deviceContext.VertexShader.Get(); - var prevVsConstantBuffer = _deviceContext.VertexShader.GetConstantBuffers(0, 1); - var prevPrimitiveTopology = _deviceContext.InputAssembler.PrimitiveTopology; - _deviceContext.InputAssembler.GetIndexBuffer(out var prevIndexBuffer, out var prevIndexBufferFormat, out var prevIndexBufferOffset); - Buffer[] prevVertexBuffer = new Buffer[1]; - int[] prevVertexBufferOffset = new int[1], prevVertexBufferStride = new int[1]; - _deviceContext.InputAssembler.GetVertexBuffers(0, 1, prevVertexBuffer, prevVertexBufferOffset, prevVertexBufferStride); - var prevInputLayout = _deviceContext.InputAssembler.InputLayout; - - // Setup viewport - _deviceContext.Rasterizer.SetViewport(0, 0, drawData.DisplaySize.X, drawData.DisplaySize.Y); - - // Bind shader and vertex buffers - int stride = Unsafe.SizeOf(); - int offset = 0; - _deviceContext.InputAssembler.InputLayout = _inputLayout; - _deviceContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_vb, stride, offset)); - _deviceContext.InputAssembler.SetIndexBuffer(_ib, Format.R16_UInt, 0); - _deviceContext.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; - _deviceContext.VertexShader.SetShader(_vertexShader, null, 0); - _deviceContext.VertexShader.SetConstantBuffer(0, _vertexConstantBuffer); - _deviceContext.PixelShader.SetShader(_pixelShader, null, 0); - _deviceContext.PixelShader.SetSampler(0, _fontSampler); - - // Setup render state - _deviceContext.OutputMerger.BlendState = _blendState; - _deviceContext.OutputMerger.BlendFactor = new RawColor4(0.0f, 0.0f, 0.0f, 0.0f); - _deviceContext.OutputMerger.DepthStencilState = _depthStencilState; - _deviceContext.Rasterizer.State = _rasterizerState; - - // Render command lists - int vtxOffset = 0; - int idxOffset = 0; - Vector2 pos = drawData.DisplayPos; - for (int n = 0; n < drawData.CmdListsCount; n++) - { - var cmdList = drawData.CmdListsRange[n]; - for (int cmdI = 0; cmdI < cmdList.CmdBuffer.Size; cmdI++) - { - var cmd = cmdList.CmdBuffer[cmdI]; - if (cmd.UserCallback != IntPtr.Zero) - { - throw new NotImplementedException(); - } - else - { - _deviceContext.Rasterizer.SetScissorRectangle((int)(cmd.ClipRect.X - pos.X), (int)(cmd.ClipRect.Y - pos.Y), - (int)(cmd.ClipRect.Z - pos.X), (int)(cmd.ClipRect.W - pos.Y)); - if (!_srvCache.TryGetValue(cmd.TextureId, out var srv)) - { - srv = new ShaderResourceView(cmd.TextureId); - _srvCache.Add(cmd.TextureId, srv); - } - - try - { - _deviceContext.PixelShader.SetShaderResource(0, srv); - _deviceContext.DrawIndexed((int)cmd.ElemCount, idxOffset, vtxOffset); - } - catch (SharpDXException e) - { - Log.Error(e.Message); - } - } - - idxOffset += (int)cmd.ElemCount; - } - - vtxOffset += cmdList.VtxBuffer.Size; - } - - // Restore modified DX state - _deviceContext.Rasterizer.SetScissorRectangles(prevScissorRects); - _deviceContext.Rasterizer.SetViewports(prevViewports); - _deviceContext.Rasterizer.State = prevRasterizerState; - _deviceContext.OutputMerger.BlendState = prevBlendState; - _deviceContext.OutputMerger.BlendFactor = prevBlendFactor; - _deviceContext.OutputMerger.BlendSampleMask = prevSampleMask; - _deviceContext.OutputMerger.DepthStencilState = prevDepthStencilState; - _deviceContext.OutputMerger.DepthStencilReference = prevStencilRef; - _deviceContext.PixelShader.SetShaderResources(0, prevPsShaderResource); - _deviceContext.PixelShader.SetSamplers(0, prevPsSampler); - _deviceContext.PixelShader.Set(prevPs); - _deviceContext.VertexShader.Set(prevVs); - _deviceContext.VertexShader.SetConstantBuffers(0, prevVsConstantBuffer); - _deviceContext.InputAssembler.PrimitiveTopology = prevPrimitiveTopology; - _deviceContext.InputAssembler.SetIndexBuffer(prevIndexBuffer, prevIndexBufferFormat, prevIndexBufferOffset); - _deviceContext.InputAssembler.SetVertexBuffers(0, prevVertexBuffer, prevVertexBufferOffset, prevVertexBufferStride); - _deviceContext.InputAssembler.InputLayout = prevInputLayout; - } - - [SuppressMessage("ReSharper", "RedundantArgumentDefaultValue")] - public bool CreateDeviceObjects() - { - if (_device == null) - return false; - if (_fontSampler == null) - InvalidateDeviceObjects(); - - // Create the vertex shader - string vertexShader = - @"cbuffer vertexBuffer : register(b0) - { - float4x4 ProjectionMatrix; - }; - struct VS_INPUT - { - float2 pos : POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; - }; - - struct PS_INPUT - { - float4 pos : SV_POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; - }; - - PS_INPUT main(VS_INPUT input) - { - PS_INPUT output; - output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f)); - output.col = input.col; - output.uv = input.uv; - return output; - }"; - - _vertexShaderBlob = ShaderBytecode.Compile(vertexShader, "main", "vs_4_0", ShaderFlags.None, EffectFlags.None); - if (_vertexShaderBlob == null) - return false; - _vertexShader = new VertexShader(_device, _vertexShaderBlob); - if (_vertexShader == null) - return false; - - // Create the input layout - _inputLayout = new InputLayout(_device, ShaderSignature.GetInputSignature(_vertexShaderBlob), - new[] - { - new InputElement("POSITION", 0, Format.R32G32_Float, 0, 0), - new InputElement("TEXCOORD", 0, Format.R32G32_Float, 8, 0), - new InputElement("COLOR", 0, Format.R8G8B8A8_UNorm, 16, 0) - }); - - // Create the constant buffer - _vertexConstantBuffer = new Buffer(_device, - new BufferDescription() - { - SizeInBytes = 4 * 4 * 4 /*TODO sizeof(Matrix4x4)*/, - Usage = ResourceUsage.Dynamic, - BindFlags = BindFlags.ConstantBuffer, - CpuAccessFlags = CpuAccessFlags.Write - }); - - // Create the pixel shader - string pixelShader = - @"struct PS_INPUT - { - float4 pos : SV_POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; - }; - sampler sampler0; - Texture2D texture0; - - float4 main(PS_INPUT input) : SV_Target - { - float4 out_col = input.col * texture0.Sample(sampler0, input.uv); - return out_col; - }"; - _pixelShaderBlob = ShaderBytecode.Compile(pixelShader, "main", "ps_4_0", ShaderFlags.None, EffectFlags.None); - if (_pixelShaderBlob == null) - return false; - _pixelShader = new PixelShader(_device, _pixelShaderBlob); - if (_pixelShader == null) - return false; - - // Create the blending setup - var blendDesc = new BlendStateDescription() { AlphaToCoverageEnable = false, IndependentBlendEnable = false }; - blendDesc.RenderTarget[0].IsBlendEnabled = true; - blendDesc.RenderTarget[0].SourceBlend = BlendOption.SourceAlpha; - blendDesc.RenderTarget[0].DestinationBlend = BlendOption.InverseSourceAlpha; - blendDesc.RenderTarget[0].BlendOperation = BlendOperation.Add; - blendDesc.RenderTarget[0].SourceAlphaBlend = BlendOption.InverseSourceAlpha; - blendDesc.RenderTarget[0].DestinationAlphaBlend = BlendOption.Zero; - blendDesc.RenderTarget[0].AlphaBlendOperation = BlendOperation.Add; - blendDesc.RenderTarget[0].RenderTargetWriteMask = ColorWriteMaskFlags.All; - _blendState = new BlendState(_device, blendDesc); - - // Create the rasterizer state - var rasterizerDesc = new RasterizerStateDescription() - { - FillMode = FillMode.Solid, - CullMode = CullMode.None, - IsScissorEnabled = true, - IsDepthClipEnabled = true - }; - _rasterizerState = new RasterizerState(_device, rasterizerDesc); - - // Create depth-stencil State - var depthStencilDesc = new DepthStencilStateDescription() - { - IsDepthEnabled = false, - DepthWriteMask = DepthWriteMask.All, - DepthComparison = Comparison.Always, - IsStencilEnabled = false - }; - depthStencilDesc.FrontFace.FailOperation = - depthStencilDesc.FrontFace.DepthFailOperation = depthStencilDesc.FrontFace.PassOperation = StencilOperation.Keep; - depthStencilDesc.BackFace = depthStencilDesc.FrontFace; - _depthStencilState = new DepthStencilState(_device, depthStencilDesc); - - CreateFontsTexture(); - - return true; - } - - void DisposeObj(ref T obj) where T : class, IDisposable - { - obj?.Dispose(); - obj = null; - } - - void InvalidateDeviceObjects() - { - if (_device == null) - return; - - try - { - // Sadly a resource leak causes this to trigger memory exceptions. - // So disabled for now - - // foreach (var entry in _srvCache) - // { - // try - // { - // entry.Value.Dispose(); - // } - // catch (Exception e) - // { - // Log.Warning($"Failed to dispose resource : {entry.Value} :{e.Message}"); - // } - // - // } - - DisposeObj(ref _fontSampler); - DisposeObj(ref _fontTextureView); - DisposeObj(ref _ib); - DisposeObj(ref _vb); - DisposeObj(ref _blendState); - DisposeObj(ref _depthStencilState); - DisposeObj(ref _rasterizerState); - DisposeObj(ref _pixelShader); - DisposeObj(ref _pixelShaderBlob); - DisposeObj(ref _vertexConstantBuffer); - DisposeObj(ref _inputLayout); - DisposeObj(ref _vertexShader); - DisposeObj(ref _vertexShaderBlob); - } - catch (Exception e) - { - Log.Warning($"Failed to dispose resources :{e.Message}"); - } - } - - private void SetPerFrameImGuiData(float deltaSeconds) - { - ImGuiIOPtr io = ImGui.GetIO(); - io.DisplaySize = new Vector2(_windowWidth / _scaleFactor.X, _windowHeight / _scaleFactor.Y); - io.DisplayFramebufferScale = _scaleFactor; - io.DeltaTime = deltaSeconds; // DeltaTime is in seconds. - } - - private static void SetKeyMappings() - { - // Todo : keymap should be defined by SystemUi - ImGuiIOPtr io = ImGui.GetIO(); - io.KeyMap[(int)ImGuiKey.Tab] = (int)Keys.Tab; - io.KeyMap[(int)ImGuiKey.LeftArrow] = (int)Keys.Left; - io.KeyMap[(int)ImGuiKey.RightArrow] = (int)Keys.Right; - io.KeyMap[(int)ImGuiKey.UpArrow] = (int)Keys.Up; - io.KeyMap[(int)ImGuiKey.DownArrow] = (int)Keys.Down; - io.KeyMap[(int)ImGuiKey.PageUp] = (int)Keys.PageUp; - io.KeyMap[(int)ImGuiKey.PageDown] = (int)Keys.PageDown; - io.KeyMap[(int)ImGuiKey.Home] = (int)Keys.Home; - io.KeyMap[(int)ImGuiKey.End] = (int)Keys.End; - io.KeyMap[(int)ImGuiKey.Delete] = (int)Keys.Delete; - io.KeyMap[(int)ImGuiKey.Backspace] = (int)Keys.Back; - io.KeyMap[(int)ImGuiKey.Enter] = (int)Keys.Enter; - io.KeyMap[(int)ImGuiKey.Escape] = (int)Keys.Escape; - io.KeyMap[(int)ImGuiKey.A] = (int)Keys.A; - io.KeyMap[(int)ImGuiKey.C] = (int)Keys.C; - io.KeyMap[(int)ImGuiKey.V] = (int)Keys.V; - io.KeyMap[(int)ImGuiKey.X] = (int)Keys.X; - io.KeyMap[(int)ImGuiKey.Y] = (int)Keys.Y; - io.KeyMap[(int)ImGuiKey.Z] = (int)Keys.Z; - } - - private unsafe void CreateFontsTexture() - { - ImGuiIOPtr io = ImGui.GetIO(); - - Icons.IconFont = io.Fonts.AddFontDefault(); - - int CustomGlyphAdder(Icons.IconSource entry) => io.Fonts.AddCustomRectFontGlyph(Icons.IconFont, entry.Char, (int)entry.SourceArea.GetWidth(), - (int)entry.SourceArea.GetHeight(), entry.SourceArea.GetWidth()); - - var glyphIds = Icons.CustomIcons.Select(CustomGlyphAdder).ToArray(); - io.Fonts.Build(); - - // Get pointer to texture data, must happen after font build - io.Fonts.GetTexDataAsRGBA32(out IntPtr atlasPixels, out var atlasWidth, out var atlasHeight, out _); - - // Load the source image - ImagingFactory factory = new ImagingFactory(); - var bitmapDecoder = new BitmapDecoder(factory, Icons.IconAtlasPath, DecodeOptions.CacheOnDemand); - var formatConverter = new FormatConverter(factory); - var bitmapFrameDecode = bitmapDecoder.GetFrame(0); - formatConverter.Initialize(bitmapFrameDecode, PixelFormat.Format32bppRGBA, BitmapDitherType.None, null, 0.0, BitmapPaletteType.Custom); - - // Copy the data into the font atlas texture - for (int i = 0; i < glyphIds.Length; i++) - { - var glyphId = glyphIds[i]; - var icon = Icons.CustomIcons[i]; - - int sx = (int)icon.SourceArea.GetWidth(); - int sy = (int)icon.SourceArea.GetHeight(); - int px = (int)icon.SourceArea.Min.X; - int py = (int)icon.SourceArea.Min.Y; - - uint[] iconContent = new uint[sx * sy]; - formatConverter.CopyPixels(new RawBox(px, py, sx, sy), iconContent); - - var rect = io.Fonts.GetCustomRectByIndex(glyphId); - for (int y = 0, s = 0; y < rect.Height; y++) - { - uint* p = (uint*)atlasPixels + (rect.Y + y) * atlasWidth + rect.X; - for (int x = rect.Width; x > 0; x--) - { - *p++ = iconContent[s]; - s++; - } - } - } - - var fontAtlasId = (IntPtr)1; - io.Fonts.SetTexID(fontAtlasId); - var box = new DataBox(atlasPixels, atlasWidth * 4, 0); - - try - { - - // Upload texture to graphics system - var textureDesc = new Texture2DDescription() - { - Width = atlasWidth, - Height = atlasHeight, - MipLevels = 1, - ArraySize = 1, - Format = Format.R8G8B8A8_UNorm, - SampleDescription = new SampleDescription() { Count = 1, Quality = 0 }, - Usage = ResourceUsage.Default, - BindFlags = BindFlags.ShaderResource, - CpuAccessFlags = CpuAccessFlags.None - }; - Texture2D texture = new Texture2D(_device, textureDesc, new[] { box }); - texture.DebugName = "FImgui Font Atlas"; - - _fontTextureView = new ShaderResourceView(_device, texture); - texture.Dispose(); - - // Store our identifier - io.Fonts.TexID = (IntPtr)_fontTextureView; - - var samplerDesc = new SamplerStateDescription() - { - Filter = Filter.MinMagMipLinear, - AddressU = TextureAddressMode.Wrap, - AddressV = TextureAddressMode.Wrap, - AddressW = TextureAddressMode.Wrap, - MipLodBias = 0.0f, - ComparisonFunction = Comparison.Always, - MinimumLod = 0.0f, - MaximumLod = 0.0f - }; - _fontSampler = new SamplerState(_device, samplerDesc); - } - catch (Exception e) - { - Log.Error("Failed to create fonts texture: " + e.Message); - } - } - - public void Dispose() - { - InvalidateDeviceObjects(); - } - } -} \ No newline at end of file diff --git a/Editor/Gui/T3UI.cs b/Editor/Gui/T3UI.cs index 7898d8bfd4..1364dbe3e7 100644 --- a/Editor/Gui/T3UI.cs +++ b/Editor/Gui/T3UI.cs @@ -15,7 +15,6 @@ using T3.Core.Logging; using T3.Core.Operator; using T3.Core.Operator.Interfaces; -using T3.Editor.Gui.Audio; using T3.Editor.Gui.Commands; using T3.Editor.Gui.Dialog; using T3.Editor.Gui.Graph.Interaction; @@ -44,7 +43,7 @@ static T3Ui() var operatorsAssembly = Assembly.GetAssembly(typeof(Value)); UiSymbolData = new UiSymbolData(operatorsAssembly, enableLog: false); - WindowManager.TryToInitialize(); + //WindowManager.TryToInitialize(); ExampleSymbolLinking.UpdateExampleLinks(); VariationHandling.Init(); @@ -64,7 +63,7 @@ private void InitializeAfterAppWindowReady() _initialed = true; } - private bool _initialed = false; + private bool _initialed; public void ProcessFrame() { @@ -173,15 +172,27 @@ private void TriggerGlobalActionsFromKeyBindings() { SaveInBackground(saveAll:true); } - else if (KeyboardBinding.Triggered(UserActions.ToggleFocusMode)) + else if (KeyboardBinding.Triggered(UserActions.ToggleAllUiElements)) { - ToggleFocusMode(); + ToggleAllUiElements(); } else if (KeyboardBinding.Triggered(UserActions.SearchGraph)) { _searchDialog.ShowNextFrame(); } - + else if (KeyboardBinding.Triggered(UserActions.ToggleFullscreen)) + { + UserSettings.Config.FullScreen = !UserSettings.Config.FullScreen; + } + else if (KeyboardBinding.Triggered(UserActions.ToggleFocusMode)) ToggleFocusMode(); + } + + private static void ToggleFocusMode() { + var shouldBeFocusMode = !UserSettings.Config.FocusMode; + UserSettings.Config.FocusMode = shouldBeFocusMode; + UserSettings.Config.ShowToolbar = shouldBeFocusMode; + ToggleAllUiElements(); + LayoutHandling.LoadAndApplyLayoutOrFocusMode(shouldBeFocusMode ? 11 : UserSettings.Config.WindowLayoutIndex); } private void DrawAppMenuBar() @@ -270,6 +281,15 @@ private void DrawAppMenuBar() { ExportWikiDocumentation.ExportWiki(); } + if (ImGui.MenuItem("Export Documentation to JSON")) + { + ExportDocumentationStrings.ExportDocumentationAsJson(); + } + if (ImGui.MenuItem("Import documentation from JSON")) + { + ExportDocumentationStrings.ImportDocumentationAsJson(); + } + ImGui.EndMenu(); } @@ -294,13 +314,46 @@ private void DrawAppMenuBar() ImGui.MenuItem("Show Minimap", "", ref UserSettings.Config.ShowMiniMap); ImGui.MenuItem("Show Toolbar", "", ref UserSettings.Config.ShowToolbar); ImGui.MenuItem("Show Interaction Overlay", "", ref UserSettings.Config.ShowInteractionOverlay); - if(ImGui.MenuItem("Toggle All UI Elements", KeyboardBinding.ListKeyboardShortcuts(UserActions.ToggleFocusMode, false), false, !IsCurrentlySaving)) + if(ImGui.MenuItem("Toggle All UI Elements", KeyboardBinding.ListKeyboardShortcuts(UserActions.ToggleAllUiElements, false), false, !IsCurrentlySaving)) { - ToggleFocusMode(); + ToggleAllUiElements(); } ImGui.Separator(); - ImGui.MenuItem("FullScreen", "", ref UserSettings.Config.FullScreen); + if (ImGui.BeginMenu("Main Window Fullscreen Destination")) + { + for (var index = 0; index < EditorUi.AllScreens.Length; index++) + { + var screen = EditorUi.AllScreens.ElementAt(index); + var label = $"{screen.DeviceName.Trim(new char[] { '\\', '.' })}" + + $" ({screen.Bounds.Width}x{screen.Bounds.Height})"; + if(ImGui.MenuItem(label, "", index == UserSettings.Config.FullScreenIndexMain)) + { + UserSettings.Config.FullScreenIndexMain = index; + } + } + ImGui.EndMenu(); + } + if(ImGui.BeginMenu("Viewer Window Fullscreen Destination")) + { + for (var index = 0; index < EditorUi.AllScreens.Length; index++) + { + var screen = EditorUi.AllScreens.ElementAt(index); + var label = $"{screen.DeviceName.Trim(new char[] { '\\', '.' })}" + + $" ({screen.Bounds.Width}x{screen.Bounds.Height})"; + if(ImGui.MenuItem(label, "", index == UserSettings.Config.FullScreenIndexViewer)) + { + UserSettings.Config.FullScreenIndexViewer = index; + } + } + ImGui.EndMenu(); + } + + ImGui.MenuItem("Fullscreen", KeyboardBinding.ListKeyboardShortcuts(UserActions.ToggleFullscreen, false), ref UserSettings.Config.FullScreen); + if (ImGui.MenuItem("Focus Mode", KeyboardBinding.ListKeyboardShortcuts(UserActions.ToggleFocusMode, false), UserSettings.Config.FocusMode)) + { + ToggleFocusMode(); + } ImGui.EndMenu(); } @@ -310,7 +363,6 @@ private void DrawAppMenuBar() ImGui.EndMenu(); } - if (UserSettings.Config.FullScreen) { ImGui.Dummy(new Vector2(10,10)); @@ -323,8 +375,7 @@ private void DrawAppMenuBar() T3Metrics.DrawRenderPerformanceGraph(); - - _statusErrorLine.Draw(); + Program.StatusErrorLine.Draw(); ImGui.EndMainMenuBar(); } @@ -333,7 +384,7 @@ private void DrawAppMenuBar() } - private void ToggleFocusMode() + private static void ToggleAllUiElements() { //T3Ui.MaximalView = !T3Ui.MaximalView; if (UserSettings.Config.ShowToolbar) @@ -449,10 +500,8 @@ private static void CountSymbolUsage() } } - private readonly StatusErrorLine _statusErrorLine = new(); public static readonly UiSymbolData UiSymbolData; - - + public static IntPtr NotDroppingPointer = new IntPtr(0); public static bool DraggingIsInProgress = false; public static bool MouseWheelFieldHovered { private get; set; } diff --git a/Editor/Gui/Templates/CreateFromTemplateDialog.cs b/Editor/Gui/Templates/CreateFromTemplateDialog.cs index 4a7c4d31fb..c013db5101 100644 --- a/Editor/Gui/Templates/CreateFromTemplateDialog.cs +++ b/Editor/Gui/Templates/CreateFromTemplateDialog.cs @@ -36,7 +36,7 @@ public void Draw() ImGui.GetWindowDrawList().AddRectFilled(windowMin, windowMin + ImGui.GetContentRegionAvail(), UiColors.BackgroundButton); - FormInputs.ResetIndent(); + FormInputs.SetIndentToParameters(); //ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, new Vector2(10,10)); //ImGui.PushStyleVar(ImGuiStyleVar.ItemInnerSpacing, new Vector2(4, 4)); diff --git a/Editor/Gui/Templates/TemplateUse.cs b/Editor/Gui/Templates/TemplateUse.cs index 344cb85b9c..9f19020679 100644 --- a/Editor/Gui/Templates/TemplateUse.cs +++ b/Editor/Gui/Templates/TemplateUse.cs @@ -5,6 +5,7 @@ using T3.Editor.Gui.Graph.Interaction; using T3.Editor.Gui.Graph.Modification; using T3.Editor.Gui.UiHelpers; +using T3.Editor.UiModel; namespace T3.Editor.Gui.Templates { diff --git a/Editor/Gui/UiHelpers/Helpers.cs b/Editor/Gui/UiHelpers/Helpers.cs index 15c1d93c23..042ebba55f 100644 --- a/Editor/Gui/UiHelpers/Helpers.cs +++ b/Editor/Gui/UiHelpers/Helpers.cs @@ -30,6 +30,9 @@ public static ImDrawListPtr OutlinedRect(ref ImDrawListPtr drawList, Vector2 pos /// public static void DebugRect(Vector2 screenMin, Vector2 screenMax, string label = "") { + if (string.IsNullOrEmpty(label)) + return; + var overlayDrawlist = ImGui.GetForegroundDrawList(); overlayDrawlist.AddRect(screenMin, screenMax, Color.Green); overlayDrawlist.AddText(new Vector2(screenMin.X, screenMax.Y), Color.Green, label); @@ -39,6 +42,9 @@ public static void DebugRect(Vector2 screenMin, Vector2 screenMax, Color color, { var overlayDrawlist = ImGui.GetForegroundDrawList(); overlayDrawlist.AddRect(screenMin, screenMax, color); + if (string.IsNullOrEmpty(label)) + return; + overlayDrawlist.AddText(new Vector2(screenMin.X, screenMax.Y), color, label); } diff --git a/Editor/Gui/UiHelpers/KeyboardAndMouseOverlay.cs b/Editor/Gui/UiHelpers/KeyboardAndMouseOverlay.cs index ac923d4745..5642361757 100644 --- a/Editor/Gui/UiHelpers/KeyboardAndMouseOverlay.cs +++ b/Editor/Gui/UiHelpers/KeyboardAndMouseOverlay.cs @@ -68,9 +68,43 @@ public static void Draw() var color = ImGui.IsMouseDown(ImGuiMouseButton.Middle) ? UiColors.ForegroundFull.Fade(_widgetFade) : UiColors.ForegroundFull.Fade(0.1f * _widgetFade); center.X -= 1; - var width = new Vector2(14, 24); - var min = center- width * 0.5f + new Vector2(0,6); - dl.AddRectFilled(min, min + width, color, 10); + var size = new Vector2(14, 24); + var min = center- size * 0.5f + new Vector2(0,6); + dl.AddRectFilled(min, min + size, color, 10); + } + + // mouse wheel + { + var fadeFromTime = 1-(float)((Playback.RunTimeInSecs - _lastMouseWheelInteractionTime) / FadeoutDuration).Clamp(0, 1); + var mouseDelta = ImGui.GetIO().MouseWheel; + if (mouseDelta != 0) + { + _lastMouseWheelInteractionTime = Playback.RunTimeInSecs; + _lastInteractionTime = Playback.RunTimeInSecs; + _wheelSpin -= mouseDelta; + } + + _dampedWheelSpin = DampFunctions.DampenFloat(_wheelSpin, _dampedWheelSpin, 0.001f, ref _dampedWheelSpinVelocity, DampFunctions.Methods.DampedSpring); + if (double.IsInfinity(_dampedWheelSpin) || double.IsNaN(_dampedWheelSpin)) + { + _dampedWheelSpin = 0; + } + + const int lineCount = 5; + const float height = 34; + var size = new Vector2(9, 1); + var min = center- size * 0.5f + new Vector2(0,-10); + float step = height / (lineCount + 1); + + for (int i = 0; i < lineCount; i++) + { + var f = (float)i / lineCount; + var fadeEdge =1- MathF.Abs((f - 0.5f) * 2).Clamp(0, 1); + var offset = new Vector2(0, step * i + step * MathUtils.Fmod(_dampedWheelSpin + 0.5f, 1)); + + var color = UiColors.ForegroundFull.Fade(fadeFromTime * fadeEdge); + dl.AddRectFilled(min + offset, min + size + offset, color, 10); + } } } @@ -132,6 +166,7 @@ private static void UpdatePressedKeys() private static readonly List _previousKeys = new(); private static double _lastInteractionTime = double.NegativeInfinity; private static float _widgetFade = 0; + private static double _lastMouseWheelInteractionTime; private class KeyStatus { @@ -164,9 +199,12 @@ public float FadeProgress } - private const float FadeoutDuration = 2; + private const float FadeoutDuration = 2; private const int KeyLookupCount = 512; + private static float _wheelSpin; + private static float _dampedWheelSpin; + private static float _dampedWheelSpinVelocity; private static readonly KeyStatus[] _keyStates = new KeyStatus[KeyLookupCount]; diff --git a/Editor/Gui/UiHelpers/StatusErrorLine.cs b/Editor/Gui/UiHelpers/StatusErrorLine.cs index 8d27f35a4c..9d8cf6c4b1 100644 --- a/Editor/Gui/UiHelpers/StatusErrorLine.cs +++ b/Editor/Gui/UiHelpers/StatusErrorLine.cs @@ -14,11 +14,6 @@ namespace T3.Editor.Gui.UiHelpers /// public class StatusErrorLine : ILogWriter { - public StatusErrorLine() - { - Log.AddWriter(this); - } - public void Draw() { lock (_logEntries) diff --git a/Editor/Gui/UiHelpers/SymbolTreeMenu.cs b/Editor/Gui/UiHelpers/SymbolTreeMenu.cs index aa186b5618..6ae1c393ad 100644 --- a/Editor/Gui/UiHelpers/SymbolTreeMenu.cs +++ b/Editor/Gui/UiHelpers/SymbolTreeMenu.cs @@ -5,11 +5,16 @@ using ImGuiNET; using T3.Core.Logging; using T3.Core.Operator; +using T3.Editor.Gui.Commands; +using T3.Editor.Gui.Commands.Graph; using T3.Editor.Gui.Graph; using T3.Editor.Gui.Graph.Interaction; +using T3.Editor.Gui.Graph.Interaction.Connections; using T3.Editor.Gui.InputUi; +using T3.Editor.Gui.Interaction.Variations; using T3.Editor.Gui.Styling; using T3.Editor.Gui.Windows; +using T3.Editor.UiModel; namespace T3.Editor.Gui.UiHelpers { @@ -80,7 +85,7 @@ public static void DrawSymbolItem(Symbol symbol) { ImGui.SetMouseCursor(ImGuiMouseCursor.ResizeAll); } - + ImGui.PopStyleColor(4); HandleDragAndDropForSymbolItem(symbol); @@ -92,10 +97,10 @@ public static void DrawSymbolItem(Symbol symbol) { SymbolLibrary._listUsagesFilter = symbol; } + ImGui.PopStyleColor(); } - if (SymbolUiRegistry.Entries.TryGetValue(symbol.Id, out var symbolUi)) { if (!string.IsNullOrEmpty(symbolUi.Description)) @@ -128,7 +133,6 @@ public static void DrawSymbolItem(Symbol symbol) ImGui.PopStyleVar(); ImGui.PopFont(); } - } ImGui.PopID(); } @@ -138,7 +142,7 @@ private static bool ListSymbolSetWithTooltip(string setTitleFormat, string empty var activated = false; ImGui.PushID(setTitleFormat); ImGui.SameLine(); - + if (symbolIdSet.Count == 0) { ImGui.TextUnformatted(emptySetTitle); @@ -158,7 +162,7 @@ private static bool ListSymbolSetWithTooltip(string setTitleFormat, string empty activated = true; } } - + ImGui.PopID(); return activated; } @@ -176,7 +180,6 @@ private static void ListSymbols(HashSet valueRequiredSymbolIds) } } - private static bool IsSymbolCurrentCompositionOrAParent(Symbol symbol) { var comp = GraphWindow.GetPrimaryGraphWindow()?.GraphCanvas?.CompositionOp; @@ -195,30 +198,22 @@ private static bool IsSymbolCurrentCompositionOrAParent(Symbol symbol) { if (instance.Symbol == symbol) return true; - + instance = instance.Parent; } return false; } - - - + public static void HandleDragAndDropForSymbolItem(Symbol symbol) { - - if (ImGui.IsItemActivated()) - { - Log.Debug("Can't insert that symbol because it would create a cycle."); - return; - } - if (ImGui.IsItemActive()) { if (IsSymbolCurrentCompositionOrAParent(symbol)) { return; } + if (ImGui.BeginDragDropSource()) { if (_dropData == new IntPtr(0)) @@ -236,6 +231,14 @@ public static void HandleDragAndDropForSymbolItem(Symbol symbol) } else if (ImGui.IsItemDeactivated()) { + if (ImGui.GetMouseDragDelta().Length() < 4) + { + if (NodeSelection.GetSelectedChildUis().Count() == 1) + { + ConnectionMaker.InsertSymbolInstance(symbol); + } + } + _dropData = new IntPtr(0); } } diff --git a/Editor/Gui/UiHelpers/UserSettings.cs b/Editor/Gui/UiHelpers/UserSettings.cs index e6dc5a9c3d..e9611393c1 100644 --- a/Editor/Gui/UiHelpers/UserSettings.cs +++ b/Editor/Gui/UiHelpers/UserSettings.cs @@ -44,16 +44,19 @@ public class ConfigData // UI-State public float UiScaleFactor = 1; public bool FullScreen = false; + public bool FocusMode = false; public int WindowLayoutIndex = 0; public bool EnableIdleMotion = true; + public bool SuspendRenderingWhenHidden = true; // Interaction public bool WarnBeforeLibEdit = true; public bool SmartGroupDragging = false; public bool ShowExplicitTextureFormatInOutputWindow = false; public bool UseArcConnections = true; + public bool ResetTimeAfterPlayback; public float SnapStrength = 5; - public bool UseJogDialControl = true; + public ValueEditGizmos ValueEditGizmo; public float ScrollSmoothing = 0.1f; public float ClickThreshold = 5; // Increase for high-res display and pen tablets @@ -77,7 +80,9 @@ public class ConfigData // Other settings public float GizmoSize = 100; - public bool SwapMainAnd2ndWindowsWhenFullscreen = false; + public int FullScreenIndexMain = 0; + public int FullScreenIndexViewer = 0; + // Timeline public float TimeRasterDensity = 1f; @@ -95,8 +100,14 @@ public class ConfigData public List GradientPresets = new(); public string ColorThemeName; + } - + public enum ValueEditGizmos + { + InfinitySlider, + RadialSlider, + JogDial, + ValueLadder, } public static bool IsUserNameDefined() diff --git a/Editor/Gui/UiHelpers/Wiki/ExportDocumentationStrings.cs b/Editor/Gui/UiHelpers/Wiki/ExportDocumentationStrings.cs new file mode 100644 index 0000000000..4ad5153ebe --- /dev/null +++ b/Editor/Gui/UiHelpers/Wiki/ExportDocumentationStrings.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using T3.Core.Logging; +using T3.Editor.UiModel; +using T3.Serialization; +// ReSharper disable NotAccessedField.Local + +namespace T3.Editor.Gui.UiHelpers.Wiki +{ + /// + /// Exports a json string for automatically review and correction. + /// + public static class ExportDocumentationStrings + { + + public static void ExportDocumentationAsJson() + { + var results = new List(); + + foreach (var symbolUi in SymbolUiRegistry.Entries.Values) + { + if (!string.IsNullOrWhiteSpace(symbolUi.Description)) + { + results.Add(new DocumentationEntry + { + Type = DocumentationEntry.Types.Description, + Text = symbolUi.Description, + SymbolId = symbolUi.Symbol.Id, + Id = Guid.Empty + }); + } + + foreach (var annotation in symbolUi.Annotations.Values) + { + results.Add(new DocumentationEntry + { + Type = DocumentationEntry.Types.Annotation, + Text = annotation.Title, + SymbolId = symbolUi.Symbol.Id, + Id = annotation.Id + }); + } + + foreach (var childUi in symbolUi.ChildUis) + { + if (string.IsNullOrWhiteSpace(childUi.Comment)) + continue; + + results.Add(new DocumentationEntry + { + Type = DocumentationEntry.Types.Comment, + Text = childUi.Comment, + SymbolId = symbolUi.Symbol.Id, + Id = childUi.Id + }); + } + + JsonUtils.SaveJson(results, DocumentationJsonFilename); + } + } + + + public static void ImportDocumentationAsJson() + { + var results = JsonUtils.TryLoadingJson>(DocumentationJsonFilename); + if (results == null) + { + Log.Warning($"Failed to load or parse {DocumentationJsonFilename}"); + return; + } + + foreach (var r in results) + { + if (SymbolUiRegistry.Entries.TryGetValue(r.SymbolId, out var symbolUi)) + { + switch (r.Type) + { + case DocumentationEntry.Types.Description: + symbolUi.Description = r.Text; + + break; + + case DocumentationEntry.Types.Annotation: + if (symbolUi.Annotations.TryGetValue(r.Id, out var a)) + { + a.Title = r.Text; + } + break; + + case DocumentationEntry.Types.Comment: + var childUi= symbolUi.ChildUis.FirstOrDefault(c => c.Id == r.Id); + if (childUi != null) + { + childUi.Comment = r.Text; + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + symbolUi.FlagAsModified(); + } + } + } + + + private class DocumentationEntry + { + public enum Types + { + Description, + Annotation, + Comment, + } + + public Types Type; + public string Text; + public Guid SymbolId; + public Guid Id; + } + + private const string DocumentationJsonFilename = "documentation.json"; + + } +} \ No newline at end of file diff --git a/Editor/Gui/UiHelpers/Wiki/ExportWikiDocumentation.cs b/Editor/Gui/UiHelpers/Wiki/ExportWikiDocumentation.cs index 0e18762f12..05e2fe25d8 100644 --- a/Editor/Gui/UiHelpers/Wiki/ExportWikiDocumentation.cs +++ b/Editor/Gui/UiHelpers/Wiki/ExportWikiDocumentation.cs @@ -6,6 +6,7 @@ using T3.Core.Logging; using T3.Core.Operator; using T3.Editor.Gui.InputUi; +using T3.Editor.UiModel; namespace T3.Editor.Gui.UiHelpers.Wiki { diff --git a/Editor/Gui/Windows/ConfigurationTest.cs b/Editor/Gui/Windows/ConfigurationTest.cs new file mode 100644 index 0000000000..675dd245ae --- /dev/null +++ b/Editor/Gui/Windows/ConfigurationTest.cs @@ -0,0 +1,401 @@ +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using ImGuiNET; +using T3.Core.Logging; +using T3.Editor.Gui.Styling; + +// ReSharper disable StringLiteralTypo +// ReSharper disable FieldCanBeMadeReadOnly.Local +// ReSharper disable ClassNeverInstantiated.Local +// ReSharper disable ArrangeTypeMemberModifiers + +namespace T3.Editor.Gui.Windows; + +internal static class ConfigurationTest +{ + #region user interface + public static void Draw() + { + FormInputs.SetIndentToParameters(); + ImGui.Indent(20); + FormInputs.AddSectionHeader("Category test"); + + if (!_initialized) + { + ImportFromCsv(); + _initialized = true; + } + + if (ImGui.TreeNode("Definition")) + { + if (ImGui.InputTextMultiline("Options (Tab Separated)", ref _optionsAsCvs, 100000, new Vector2(800, 200))) + { + ImportFromCsv(); + } + + ImGui.TreePop(); + } + + DrawCategorySelection(); + DrawSelectedOptions(); + } + + private static void DrawCategorySelection() + { + if (!ImGui.TreeNode("Categories:")) + return; + + foreach (var c in _categories) + { + TryGetValidOptionsForCategory(c, out var validOptions); + if (validOptions.Count < 2) + { + ImGui.PushStyleColor(ImGuiCol.Text, UiColors.TextMuted.Rgba); + ImGui.Text(c.Id + $" ({validOptions.Count})"); + ImGui.PopStyleColor(); + continue; + } + + var isCurrent = _selectedCategory == c; + + var suffix = validOptions.Count > 0 + ? $" ({validOptions.Count} options)" + : string.Empty; + + if (ImGui.Selectable($"{c.Id} {suffix}", isCurrent)) + _selectedCategory = c; + + if (isCurrent) + DrawCategoryOptions(validOptions); + } + + ImGui.TreePop(); + } + + private static void DrawCategoryOptions(List