AU Class
AU Class
class - AU

Dynamo for Software Developers: C#, Python, and More—Workshop - Part 4 of 4

Share this class
Search for keywords in videos, presentation slides and handouts:

Description

Are the out of the box nodes in Dynamo not enough? Ever felt like you wanted a way to customize the Dynamo experience for not only your team but your clients? Then come join us for the Dynamo for Software Developers workshop! You’ll learn how to extend Dynamo by using code to develop on top of it. We will teach you when and how to use different development tools to build your own nodes using C# and Python. We will even teach you how to manipulate the Dynamo experience using extensions to build custom UI or interactions. Please note: This class is targeted at software developers with experience writing source code: We will not be covering entry level Dynamo. If you are a beginner or have never used Dynamo before consider attending the Dynamo Beginner session held during the main AU conference or invest in beginner training ahead of time.Participants will be paired at provided computers (1 computer for 2 participants). Includes the Tuesday AU General Session. Don’t forget to add the AU Full Conference Pass and sign up for the Wednesday evening DynaLightning talks and party.

Key Learnings

  • Learn when and how to Use Python in Dynamo
  • Learn C# basics and how to use the Revit API in Dynamo
  • Learn how to build your own zero-touch, read-only nodes using C#
  • Learn how to control and manipulate the Dynamo UI and interactions using Extensions

Speakers_few

  • Фотография профиля Thomas Mahon
    Thomas Mahon
    Founding Director of Bimorph Consultancy, Software Engineer and computational design/BIM specialist. Creator of bimorphNodes. Authorized Autodesk Developer. Bimorph is a digital engineering firm transforming the way Architects, Engineers and Building Contractors realise buildings
  • Racel Williams
    Racel Williams is an AI Development Manager for the Building, Infrastructure, and Design Group. She has a B.S. in Marketing from the University of Florida and Master’s degrees in Architecture and Human-Computer Interaction from Georgia Tech where her research focus was Augmented Reality and Tangible Interaction. In 2013, she joined Autodesk as an intern where she developed a mobile AR prototype for in-situ annotation and visualization. After becoming full-time, she went on to become the UX Designer for FormIt, Dynamo, and other related projects. Later, she became the Product Owner of Dynamo and led the development team in shipping multiple versions of Dynamo. She has given numerous talks and workshops on Dynamo around the world. Currently, she is now helping Autodesk shape how the company will integrate AI and Machine Learning in AEC workflows by leading a team of ML researchers and engineers to build the next generation of AEC tools.
Video Player is loading.
Current Time 0:00
Duration 1:23:37
Loaded: 0.20%
Stream Type LIVE
Remaining Time 1:23:37
 
1x
  • Chapters
  • descriptions off, selected
  • en (Main), selected
Transcript

PRESENTER 1: Cool. So now that we're back everyone, Tom is going to explain to you why it didn't work and why it was my fault, as usual. Blame the other guy, you know. And then, we're going to go straight into extensions up until 5:00, and we're going to do a bunch of stuff. So hang in there. I know it's been a long day. It's only got 90 minutes left so. Tom.

PRESENTER 2: Just so it's on record. OK, so the issue here-- and actually, it's kind of good this happened because, of course, when you guys go about your offices and you can boast that you don't know Seashell from Python and you start writing all of your own nodes, this is going to happen. You're going to have this amazing script. You've run it, and then of course, it doesn't work. And it can be very frustrating.

So there's many different ways of addressing these kind of issues. The most common is actually debugging, which unfortunately, we can't show you today. But maybe actually afterwards, we can show you because it's an important skill to have. But anyway, if I run this, first of all, does it run? The answer is yes. It's definitely running because I'm getting desk coming out of there. The problem is, I can't see them anywhere. So what's the issue?

So the most obvious thing that I do is just click on the ID. And Revit is showing me the desk. And by the looks of things, that isn't desk. So I'm like, hey, well, it's selected. So I'll go to view. And then I do-- where's that crop box [INAUDIBLE]. OK, try that again. Yeah. OK, so if I'm try to select this, it's showing me literally nothing.

But I can select the desk somehow. Let me just trying to find it. OK. OK, this is my desk. Although it doesn't look like much of a desk, but I managed to locate it. If I click on this desk, you'll notice that when I do edit type, with the depth above 0. So that explains the problem. Thanks, [INAUDIBLE].

So yeah, so this node, of course, is a reliance. It's called dependency on the desk arrangement object. So when it's reading all the desks, of course, those abstract desks have a 0 length and a 0 width. So in this case, the solution would be to go back into our code, update that desk object so it actually has a valid length and width, and then, of course, we just recompile and rerun it and it's problem solved.

And then, we can always just check this manually if I go in and modify this. And then apply. I've now got proper desks again. So I know that's definitely the problem. So yeah, these things happen. It's not a bad thing. You are only human. You will invariably make mistakes. Or you get a phone call, and then before you know it's broken your train of thought. I mean, you forget to update something and you run it. And before you know it, it doesn't work anymore. And it's very common.

So in actual fact, that's not a bad thing that happened in the workshop because that actually gives you guys, once again, more insight into the types of scenarios which are going to occur when you start developing. And do not get disheartened because it's going to happen, and it's going to be frustrating. But perseverance pays. That's the one takeaway that I've got about coding.

The individuals that tend to excel are the ones that when they are confronted by these kind of problems, they don't give up until they find out what the cause of the problem is. So yeah, that was the issue and that's not fixed, and it is now working. So if I go to my floor, you can see that I've got a really high density. And whoever owns the building is going to be really happy because they can rent out multiple different desks to multiple different people. But of course, you know you can see we'll also need to just resolve the spacing of the desks inside this room as well.

But either way this works. Unfortunately, we're not going to have time to do the path of egress. But in actual fact, it's a very simple Revit API call. It's literally one line of code. And you'll find that on GitHub. So there's a good opportunity for you guys to-- after the workshop, go ahead and build some more zero touch nodes using what we've got on GitHub to build those two classes, the egress result and the egress check class to give you the results about the path of egress from each desk to wherever you want to escape from.

So as I said, we're not going to have time to do that now. This gives you, again, more of an insight into how you can declare. So your [INAUDIBLE] classes level what Revit showed you. Then, declare say [INAUDIBLE] specific classes. In this case, I've declared these classes are specifically for zero touch import, which then take information from those classes and then use it to then output information that's then readable within Revit. In this case, it's the output of desks.

So yeah, that covers everything for zero touch. So hopefully that, again, gives you more ideas how you can use C # to generate your own node libraries. And as I said, check with GitHub. There's more stuff on there for the path of egress. And if you've got any questions about today's session, then please feel free to fire away now. OK, any questions? OK, good. Go ahead.

AUDIENCE: [INAUDIBLE]

PRESENTER 2: I suspect with it being the Revit API, it will just treat an L shaped room as a big square. Because Revit API treats flat surfaces as untrimmed. It's a limitation.

PRESENTER 1: The desk layout there just takes the surface, so it should work.

PRESENTER 2: Yeah, but that's my point. In Revit API the surface. Mind you-- actually, I guess if you're using Dynamo [INAUDIBLE]. OK, if you're using [INAUDIBLE] it's fine.

Yeah, there is a limitation inside Revit's geometry engine, where if you have a completely flat surface that stays L shaped, basically any trim surface, it will not treat it as trimmed. It will treat it as just one big elongated surface. And so if you plot points on an L shaped surface and use [? CV ?] prompts [INAUDIBLE] already is done. In Theory, it should follow the surface [INAUDIBLE] space. But Revit doesn't honor that if it's completely flat. So it's a bit of a flaw.

But let's try anyway. If we go for an L shaped room, let's have a look at what it actually does. And of course, if it breaks again, I'll just blame [INAUDIBLE]. OK. OK, one of the limitations that I've got is every time we're on the node, it tries to create it's family type. And if it's already created, and I try and create it again, Revit is like, nope. You can't create it again. So I always just delete it. So again, that is another limitation which it needs to update. And it's another good example of the kinds of issues which you might be confronted with yourself.

So what you do in that instance is just check that it already exists. And if it does, then just go ahead and make the modification inside the code. And of course, this would change the desk size. Because it's still 0 0.

AUDIENCE: [INAUDIBLE] just click the project [? parameter. ?]

PRESENTER 1: [INAUDIBLE]

PRESENTER 2: Yeah.

AUDIENCE: [INAUDIBLE]

PRESENTER 2: Thanks. This is [INAUDIBLE]. Yeah, so in that case, you'd perhaps want to think about other ways of sharing desks with an arrangement. There's actually many ways of resolving that. So even though there are these limitations inside Revit and [INAUDIBLE] Dynamo's geometry engine, it's not the end of the world. Because there's always methods that you can use as a developer to get around these limitations. And that's also part of the fun of it.

So yeah, there are limitations, even in the API. And you might find you've got to write clever techniques to get around it. But yeah, in this case, it's not going to handle L shaped rooms. Yeah. Great, OK. Well, thanks very much for staying alert. And I'll [INAUDIBLE] now is going to go through Dynamo extensions. Which, as you know, they're essentially just add-ins for Revit. So you can do add-ins for Revit, then the same thing for Dynamo in essence. So I'll leave it with [INAUDIBLE]. Thanks.

PRESENTER 1: OK, so we made it. We're at the end of the day. We're going to talk about extensions.

[INTERPOSING VOICES]

PRESENTER 1: Yes. I'm going to give you a very, very brief 10 minute overview of extensions, what they're capable of, and what they involve in development. Because it's quite different from doing the C # with the zero touch stuff. There's a little bit more involved. And then, we're going to dive right in and create our own extension.

I'll give you a preview at the end of what it's going to look like. But diving straight in, making an extension involves a couple of things. First one is, actually, coding the extension as a .NET assembly, like we've been doing in zero touch, for example. And you have to implement some very specific interfaces that Dynamo team have created for us. And the second thing that it involves is actually making an xml file where we declare that this is an extension, and which dll to load the extension from.

So when Dynamo starts up, it looks for these xml files. If it finds one, it's like, OK, this is an extension next xml. I'm going to look for the file that's inside of-- that it's pointing me to. And maybe I find an extension in there.

So like I said, Dynamo starts up. It looks for these things. If it finds the xml which is pointing to a dll file, which by now, you should know is what is the output of a C# project. It tries to load that dll.

Now, naming is very important, and this gets me every single time because I keep forgetting it. The name of the xml file needs to be the same as your dll, I think. So if your extension is called myextension.dll, this should be my extension_extension, not xml. The other one should be called my extension_viewextension. And we'll see the difference between the two in a second.

Which brings us to the architecture of the extensions and what happens when Dynamo tries to load one of these. So Dynamo starts-- when you first launch Dynamo, it goes through a process of starting up, right? It initializes the computing engine, and then at one point, it starts looking for these extensions or plug-ins, right? So just need to see the screen here. It gets-- I don't know if you can see my cursor. I can't see what I'm doing.

So basically, once the Dynamo engine has initialized, it starts looking for extensions, right? If it finds one, it loads the dll. And it tries to load to-- it calls a very specific method on that extension. It calls the loaded method, which tells your extension, oh, by the way, Dynamo has loaded. Here's some information about Dynamo. Then, it continues with starting up Dynamo. And then it finally reaches to a point where it initializes the user interface of Dynamo.

Then, it looks for view extensions in Dynamo, which are extensions that know about the user interface of Dynamo. So if it finds any of the extensions, it also calls the ready method on those view extensions to let the extension know Dynamo user interface is ready to be interacted with. And you can modify it or intercept it.

So as you can see, the extensions are much more powerful than zero touch nodes or the C # nodes that we were looking at because they know about Dynamo. And they can interact with it and control it, to a certain extent. So when Dynamo gives its references to these extensions, it tells, here's a reference to my user interface. There's methods on there that you can use to change the user interface and interact with it. Use it responsibly, is what Dynamo is trying to say, essentially.

So I won't go too much into this because I don't think we need to cover MVVM very much. But there is an extension manager inside Dynamo. And all this is to say is that if you develop an extension, you can actually make use of other extensions. A great example of this is the new dependency extension that we saw [INAUDIBLE] demo earlier. That one is actually calling the library extension saying, oh, are there any kind of packages installed? Give me the list of packages that are installed, and I'll see if any of the nodes missing have libraries there or not.

And then, it calls into the package manager extension and says, oh, actually install the missing one. So that's an extension that makes use of other extensions to provide this very advanced functionality. And that's what this is trying to show that you can-- if you have a view extension, you can interact with the other ones via this Dynamo extensions manager.

So what happens when Dynamo calls these startup methods in your extension? It essentially gives you a reference to some of its internal objects, which means here's a copy of who I am, and you can use this object to do stuff. So the two objects it gives you are called ready params, which you get that object when the view has loaded. This only happens in view extensions. And the other one is called start up params. It's also for the view extensions. And that means that the view is starting to be initialized.

So your extension gets called by Dynamo twice. Once when it starts initializing the view, and once when it's finished initializing the view. So if you were really mean, you could write a view extension that every time Dynamo tries starting up, it kills it. And it prevents it from starting up. No use for it whatsoever, but you have that kind of power and responsibility when you write extensions, if that makes sense. Hopefully, guys can think of better use cases than the examples I'm giving.

But in terms of like knowing what's involved in making one of these extensions, basically your view extension is aware of two things. It's aware of the Dynamo model, it's aware of the-- and aware of the Dynamo view model. I won't spend time going into view models and these things because it would take us a bit too long.

But essentially, the Dynamo view model is the middle layer, the manager that is responsible for reconciling the data of Dynamo, like the graph engine and all of those things, to the user interface. So it's the middle man between the two. It's keeping everything in sync. And that also, when you do something on the user interface, it tells the underlying Dynamo engine, oh, do the thing that was requested of you. Does that explanation make sense?

So one of the cool things about extensions is that when Dynamo calls your extension and gives you these references to these objects, you can also get access to events inside of Dynamo. So Dynamo publishes these events that essentially are triggered every time that particular thing happens. So in this example on the screen, we have an event called node added or node removed.

So every time you add a node to the canvas, Dynamo fires off this event. By the way, the node was added. Doesn't give you any more context than that. Just says, a node was added. Here's the node that was added. So you can subscribe to events like that. And basically, get notified when things happen in Dynamo and then react to them, which is what we're going to be doing today.

So let's get into it. And here's a very brief demo of what we're going to build. We're going to make a view extension that can say hello. So I'm going to start it again. So you're going to get a menu inside Dynamo that says dev workshop. You can say hello and it'll say your username. You can also launch this new window, which is like an input statistics window, which will tell you how many nodes there are on the canvas, how many connectors or wires there. And also, if any of the nodes are marked as is input, which is very useful in refinery and other places, it will list them separately in a table and it will list the current value of those inputs.

So if you have these big graphs like we do at practice, for example, you usually have a group on the left with all of your inputs. And you're all the way somewhere on the right working on your logic and you forgot what those inputs are. You could have this little window open and it would tell you what those current values would be. Obviously, an improvement for this would be to be able to click into those values and change them and that's your homework. I can't do all the work for you.

All right, so let's get into it. The first exercise we're going to do is actually make a basic extension in Dynamo. So I'm going to swap over to this other computer. So if you can open the data set. And if you go to the S4 extensions folder, you should find an exercise 1 start folder. And just open the SLN file. The Visual Studio solution inside there.

Now, what we've done to save time in workshops like this is we've prepared the solution so that whenever you build and then you press start, it automatically builds your extension. It packages up as an extension. As a dynamo package, essentially. Puts it into the right folder in Dynamo, and then launches Dynamo for you. So what this means for us is that we write some code, we press start, Dynamo is immediately fired and we see the result of our codes. If you're interested in how this is set up, there is a bigger guide on the GitHub page and other repositories. It just takes too long to set up for demos like this.

OK, so let's start adding our extension. So the first thing I'm going to do is I'm going to add a class on here. But before I do that, let me just show you these xml files so you understand what's been prepared for you. I've prepared the xml files that define an extension and the view extension. You can see that I'm going to be calling our extension Dynamo dev, and our extension actual class name should be extension sample. And the view extension is going to be called view extension example.

So because these are the names we've put in the xml, these are the names we're going to have to use for our class. If we change the class names, we're going to have to come back to the xml to change our declarations here, OK? So I'm going to close all of these, and I'm going to right click on the project which is the little C # green icon. Click add. And click on class. And I'm going to call it extension example.

Remember, to add public in front of this so we make it discoverable by Dynamo. All right, and the easiest way to do this is I'm going to write after the class name I extension, which in C # terms it means that this class needs to implement this interface. And if I hover over it and use the light bulb, it should give me a suggestion to add using Dynamo.extensions. This will not clear the red squiggly lines, but this should make extension look blue or green or whatever color this is.

And if you hover over it again, it says that it doesn't implement certain interface members. So this is where Visual Studio is very helpful, again. I don't need to necessarily go to look at the documentation and implement each one of these things by hand. I can just click the light bulb and go implement interface. So what you'll see happen is a bunch of different methods and properties have just appeared on my screen, which means that this is the contract that Dynamo gives us.

If you want to be an extension, you need to have these two properties and these four methods. And then, I can consider you an extension. So by implementing this interface, we're essentially guaranteed to be able to talk to Dynamo as an extension. At the moment, all of the methods throw a not implemented exception. That's just the code that was generated for us. So now we're going to go in and change this.

Do you still have the chrome GitHub ripper open for the snippets? In case we need to copy paste some stuff.

AUDIENCE: [INAUDIBLE] a little bigger?

PRESENTER 1: That better? Can't do much about the thing on the right hand side, unfortunately. OK, so unique idea. I'm going to delete that part. I'm going to go to my snippets. And I will copy-- well, I don't think I actually have that here. So I will have to show you guys how to generate a new unique ID. So if you go to tools and you go to Create GUID, a new window will pop up. So if you have this window, select maybe the fifth option, right? And go copy. And you can exit after that.

And if you control view on your keyboard paste, that gives you a new GUID on the canvas. And you just delete everything that is not in between the inverted commas. So all we really care about is the string that's inside that GUID. So each extension needs a GUID because it needs to be a uniquely identifiable extension. We should be familiar with this because we use these GUIDs in our C# class third year.

Name. I'm just going to give it the name extension example. And again, I have to put it in between commas. Semicolon at the end. I don't need to do anything in this post. So I can just delete that code and leave nothing on there. And for the other ones, I'm just going to delete all of these lines that say throw, and we're going to replace them with other things.

So what I was telling you about earlier, that these extensions have a certain lifecycle that Dynamo calls your extension at specific points in time when it starts up and it does things. These methods are how we interact with that. So we're building an extension right now. So we don't know about the user interface. But Dynamo is able to tell us when it's starting up. So that will be the startup method. And ready will be called once Dynamo has fully started up and is ready to be interacted with, but not in a user interface way.

So let's make some message boxes pop up just so we exactly see the result of this happening. I'm going to go to my snippets, and I'm going to copy this messagebox.show snippet. Alternatively, you can also type it out. It's not very long. So messagebox.show. And we're going to put some text in here and the extension is ready And a semicolon at the end.

And message box will be underlined with red. So just hover over it, hit the light bulb, and go ad using system.windows, which if you look at the top, it's added it for us. And that way the message box class is available for use. I'm going to copy paste this into the startup method. I'm going to change the text to say the extension is just starting up. Actually, I'm going to say Dynamo is just starting up.

You'll also notice that these methods get called with some parameters. We learned about this in the C# class. And these are the object references that I was talking about the Dynamo gives to you. So it gives you an instance of the start up parameters class. And if we pick that to see what's inside of that class, you'll see that we get a reference to the preferences of Dynamo. We get a reference to the library loader, the version of Dynamo, and a few other things. That's the startup one.

The ready one has different things available to it. So if we pick that definition, you'll see that you get a workspace model and a command executive. So this is starting to be a bit more advanced already. And if I look at that workspace model, I can continue peeking. I get a name, description, and file name for the workspace, which means you're currently open graph. And I also get connector and node models. So this is a list of all the nodes and all the connectors in your workspace graph.

So you can see that just by looking at the things that Dynamo gives us when these extensions are initialized, we can already interact with it and see what's inside Dynamo and write some code to react to that. So I think this is ready enough for us to actually test. So I want you to hit build and build solution. And if everything went right, you should see one succeeded.

And now, if I'm going to hit start, which is this button on the toolbar, what should happen and doesn't happen is we need to tell the solution where Dynamo is. So right click on the project, go properties, and if you go to the debug menu on the sidebar here. After program files, there's a slash. Just add in Autodesk over there.

So what happened is this was where Dynamo was installed last night, but today it's in a different place. Because that's how labs work. So hopefully that's the right path. So if we press start again, this time it should actually work. It's compiling in the background. Its packaging up our extension as a Dynamo package. It's putting it in the Dynamo packages folder. And then, it actually starts Dynamo.

So what you're seeing here is the message box that we created that says, Dynamo is just starting up. And notice that we get the message box, but we don't get the UI of Dynamo. We don't get anything else. This is because our extension was loaded before the user interface of Dynamo was loaded. Before even the entire engine of Dynamo was finished loading. So you get really early access to how Dynamo works.

So I'm going to click OK. And what should happen is the engine has now finished loading, so we get the extension is ready. And after that, and after some other time, Dynamo actually starts up, OK? Very exciting stuff. Message boxes appearing on a screen. But hopefully, you can see where you have a lot of power. You get early access to Dynamo and you can tell it to do stuff and modify its behavior before it's even started, and Dynamo would not even be aware that that has happened, necessarily.

Any questions so far? Anyone whose solution isn't working like this at the minute? Anyone actually trying to make it work? We've got one or two. OK. Well, shall I keep going? All right, let's see a few extension, and then we can add some code that actually does some stuff after that. So I'm going to close Dynamo and that will finish my debugging session. And I'm going to close all of these other windows I have. And I'm going to right click on the project and go add class. And I'm going to call this view extension example.

And guess what? We're going to do the exact same thing. We're going to make this a public class. And this time, we're going to implement an interface called I view extension. So they're slightly different. Again, I'm not going to hover over the light bulb and I'm going to add using Dynamo.wpf.extensions. So this is already hinting that it's a different one. Then, I can hover over the I view extension interface and tell it to implement interface.

I'm going to go back to my extension copy paste the GUID because I can't be bothered to generate a new one. Just make sure you put the quotes before you paste it in. And then, change the last two letters to 99 or something so it's different to the first one. I'm going to change the name to be view extension example. And I'm going to get rid of all of these throw statements. And I'm going to replace them with-- guess what? Message boxes again.

So Tom was telling you guys earlier how it's really important to have this debugging skill and the ability to understand what your code is doing. Message boxes are the poor man's version of that. Where if you don't know how to do that, you just put loads of message boxes everywhere. It is not the recommended way to do things. We are only doing this to demonstrate to you when these things fire. Because once a message box fires, everything else pauses until you click OK, all right? So that's why it's important to see when these things are happening.

So we've added two more message boxes in the loaded and the startup. Now, because this is a view extension, these things will come after the extension. So let's change the text to reflect that. So let's say the-- view extension, I'll make that screen is ready. And the view extension-- well, is not ready. Is starting up. And it's not the extension, but the Dynamo UI.

OK, I'm going to save and I'm going to click the Start button, which should recompile our solution and ship it to Dynamo and start Dynamo. We are still going to get the old message boxes from the extension because we're loading both the extension and the view extension. So Dynamo is just starting up. That's from our extension. The extension is ready.

The Dynamo UY is now starting up. And then, you'll see the Dynamo user interface appear. And at some point after that, the message box that tells us the Dynamo UI is ready pops up. So it shows you this clear sequence that Dynamo starts up in. Any questions on this?

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Can we?

AUDIENCE: [INAUDIBLE] the extension [INAUDIBLE].

PRESENTER 1: It behaves the exact same way. It's just when you press start, you're going to tell Revit to start. You have to manually start Dynamo in there. So as always, my suggestion do it in sandbox. Only go to Revit when you need that headache. OK, so we've got message boxes now. So what should we do next? Let's make that many item. Yeah? Got a question? Yeah.

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Just make sure that the string you pasted at the top is different from the first one. If they're the same, Dynamo will refuse to load them. Because that thing-- the extension manager that allows you to talk to other ones is the one managing these things. And it's [INAUDIBLE] it's on top of things.

OK, so let's now actually start modifying Dynamo. We know when these things are happening. I'm going to go to the extension and just get rid of these message boxes because they're going to be very annoying. And I will get rid of them and the view extension as well in the startup. I might leave it in loaded just so we know that it's still working.

And now, we want to add a menu item to Dynamo. So we are actually modifying Dynamo from the extension. So first thing I'm going to do is I'm going to add a property to the view extension here, and then I'll mark it as private because I don't want anyone else having access to this. The type will be view loaded params. And I'm going to call it view loaded params.

Now, what this is is us, basically, keeping track of this particular view loaded parameters object that Dynamo gives us when it's fully loaded. The reason we want to keep a reference to it is because to interact with Dynamo, we need to go through this object. This object is the bridge between the extension and Dynamo, essentially. So it allows us to call into Dynamo and react to it.

So in the loaded method, I'm going to go write another line of code and say, this dot view loaded parameters is equal to P, which means I'm assigning this object that Dynamo gives me to this property on our class just so I have it for reference later on and I can use it for other things.

OK, so now we want to add the menu. So how do we do that? Well, we need to interact with this view loaded parameters object. We're doing fine on time or what? OK. Cool. So I don't want to do this inside of the loaded method because it's going to become a very bloated code. And we're just going to end up stuffing a lot of stuff in here. So I'm going to make another method on here, and I'm going to say private void make-- with a capital M-- menu items. I don't need any parameters. And inside of there, I'm going to-- well, first of all, go and make a new property at the top under the view loaded parameters. I want to make a property that keeps track of our menu. So I'm going to make a private menu item extension menu.

All right, and if you hover over a menu item, hit the light bulb, you're going to get a suggestion to add system windows.controls. So going back to our make menu items method, I'm going to write this .extension menu is equal to-- what we learned in the C# class, to make a new object we have to use the new keyword. So I'm typing in new. And as soon as I do that, you see that Visual Studio suggests this is probably what you mean because you've declared it as a menu item. So suggest me to make a menu item.

And if I open the parameters-- sorry, the normal braces here, I see that it doesn't have any parameters, this constructor. So I will just make a new menu item. After I make it, I can also say this .extensionmenu.name-- or sorry, .header is assigned a string. So I'm going to call it Dynamo dev workshop.

Now, we've made the menu item. We haven't added it to Dynamo yet, but we've made an object that is a menu item. So the next thing we're going to do is we're going to add a few buttons to the menu item itself. And then after we've done that, we're going to add the entire menu to Dynamo. So the reason we have to do this is because you have to fully construct that menu and it's sub items and what happens when you click them, and only then add them to Dynamo. Otherwise, you can't add things after the fact.

I think you can't. You can't, right? No. OK, so let's make a new sub menu item now. I'm going to declare a new variable, so I'm just going to type in var. And I'm going to say that it's called say hello menu item is a new menu item. Right, and so that I don't have to make a new line and say that it's header is a specific text, I can open curly braces and just type in header is assigned say hello.

So this syntax in C# makes the object and then assigns the property header on that object to the text I'm writing in that curly brace. So those two things in one, and that's just a little bit shorter to type out. Is everyone following up to this point? Yeah? OK, don't see many people typing.

OK, the last thing we're going to do is we're going to add the behavior to this menu item so you see how that's done. And I'm going to type in say hello menu.click. And you can see that it's got the little thunderbolt symbol. This is C#'s and Visual Studio way of telling us this is an event. So what we're going to do is we're going to add something to this event. So I'm going to type in plus equals.

i won't get into the technicals of this, but for those of you don't want to follow this up at home, these are called delegates. And the property of delegates in C# is that they're multicast. Meaning that if I have a delegate, I can add multiple things to it. Long story short, this is an event that fires. And I can add things that listen to that event. And when it fires, we get notified.

So what's happening here we're saying, every time this say hello menu item is clicked, I will essentially make a new method here. And I'm using a syntax here which is basically making an anonymous method which will do certain things. So I will let you catch up with this because it's quite weird syntax. We could use a different syntax. We could make the method somewhere else in our code and then just pass in the name. But for things like this where it's a one line of code, you sometimes just want to do it in line like this, right? So make sure you follow this syntax.

After the plus equals, we have a sender in arguments in between brackets. And this is just like a method signature. And then, we have that equals and greater than symbol, which tells us this method should actually be associated with this function body. So inside here, inside the curly braces, we're going to do a message box.show. And you are probably bored of message boxes by now. And we're going to type in hello plus, and this is where we're going to add a bit of something else. Environments.username for example.

So what I'm doing here is I'm saying, show a message box, and the content of that will be hello. But when it calls this, it's actually going to tell to the computer, what's the username of the user that's currently logged in? Take that username, put it next to hello, and then that's what's going to show up.

So let's test if this works. But before we can do that, we actually need to add this menu item back into Dynamo itself. So let's do that. So this say hello menu item needs to go into our extension menu. So we will go this.extensionmenu items.add. And we add our say hello menu item.

And then, we go this.viewloadedparameters. This is that last step. We've added our sub menu to our extension menu, and now we're adding the entire extension menu to the Dynamo menu. So to do that, we have to go through that view loaded parameters object that we were talking about. And I have a method here called add menu item. I think this is a new one. It didn't used to be in the Dynamo API. Do I trust it, or do I go the old route?

OK, add menu item. And I give it this.extensionmenu. Now, this one's a menu bar type and all sorts of other things, so let's not use that. So this.viewloadedparamters. You'll see that there is a property called Dynamo menu. It's a read only one, but we can still use it. .items.add. And then, we can say this.extension menu.

So this last step is basically adding it to Dynamo. You don't have to type out the comment, this is just a code comment. I'm leaving it there so you see what that bit does. So the very last step to do is now, actually, call this make menu items method somewhere where it makes sense. And where it actually makes sense is in the loaded method at the end after we've recorded our view loaded parameters.

And basically, because we've already taken reference to that view loaded parameters object, we can call these methods. And it's a little bit cleaner to separate these things out. So now, if everything went OK, I press save and I click start. Dynamo should be starting. And once the UI is ready, we'll get that message box. View extension is ready.

And if you look here in the background, you see that there's no menu item to Dynamo yet. So our message box gets fired first, and then we add the menu item. So as soon as I click OK, a menu item should appear. And it's there. Dynamo dev.workshop. We also saw refinery appear after our message box, which tells you that refinery is also a view extension, which adds these things the same way we are doing.

So the refinery team, for example, isn't using anything that we don't have access to. In Dynamo, they're using the same kind of extensions API. So let's click on that menu item. I'll just get this bit out of the way. Dynamo dev workshop. We only have one sub menu item, which is say hello. And if I tap it, this says hello frame. We're all going to be frame today because it's frame. But on your computer at home, it should say hello [INAUDIBLE] or Marcel or whatever your computer username is.

Cool. So that's pretty much done in terms of a basic view extension that does just about nothing other than set up the structure of it and say hello back. So what I would suggest now is minimize the solution for a bit, go back to the data sets, and go to exercise one complete. Launch that.

We're going to have to do that same step right click on the project, go properties, and go to the debug menu. And after program files, go Autodesk and then another slash so that we tell it where Dynamo is situated. And then, when we press start, this is the full sample of where we should be with the exercise if we follow the steps in the repo on GitHub.

And what I've basically done is I've added two more sub menu items compared to what we've done. Extension is ready. I told you this gets old quite quickly. View extension is ready. And we have this menu. We have say hello, which does the same thing as what we did. But we also have this other method which says hack. Now, should I press that? All right, very good people. Hack, OK? And it takes us to GIPHY, and we see a congratulations gif.

So you've made it this far. We are adding extensions to Dynamo and we are changing its behavior. Before we move on to the next exercise, any questions? No? OK, let's see how we're doing for time and depending on that we decided to do everything or not. 35?

OK, sorry that was the wrong thing. I will close Dynamo and I will close this solution, and I will open exercise two start. Again, I'm going to have to go right click on the project, go properties, debug, and add Autodesk on here so that we can see what we're doing and launch Dynamo. Close all the windows.

And the next thing I want to show you is how to actually react to these events and Dynamo. So for example, when a node is added to the canvas, we should get notified that a node was added to the canvas and some information about that node. Because it's a class, we're not going to do anything with it other than show a message box. But you can imagine saving that information out to a CSV or a database somewhere. And that's the basic bones of an analytics plugin for Dynamo, right?

If you're curious, the Dynamo hackathon in London, the winners built something called binoculars. It's open source on GitHub. And do they use this exact same recipe. We actually taught them how to do extensions. And they made a basic plugin that sends analytics to the Google Data Studio cloud where they made a little dashboard. So it's quite simple and easy to put these things together. But to do that, we need to be able to listen to events in Dynamo.

So let's right click on the project and add the new class that will handle events. So I'll add a new class and I'll go quite quickly and I'll call this events. So we could be doing all of this in the view extension code, but I don't necessarily like doing everything in one single class. It's good to kind things out.

OK, now we have a class. I'm going to add a method here. I'm going to make it public static. I'm going to make the events class static as well. And I'm going to call it-- I'm going to say it's void so it doesn't return anything. It's just the method that gets fired. I'm going to call it current workspace changed. And I can't spell. This is a very bad keyboard.

Now, I'm not really going to do much in here. So I will add maybe another method. But actually, I'm going to finish this one before I do anything else. So I want this method to be called, essentially, every time you open a dynamo file or the workspace has changed. Dynamo will call this method. You'll get notified that a new file was opened. And you should know something about that file.

Now, the mechanism to do that is a parameter. And the parameter we need to add is in a name space called Dynamo.graph.workspaces.Iworkspacemodel. And I'm just going to call this workspace, right? If you're wondering how I knew that, you go to the view extension example, you look at the view start up parameters, you pick that guy, and you see all of the things that it gives you. Maybe not the startup, the loaded one. Reloaded parameters. And it gives me this-- where is it? Somewhere in here. There's an events, essentially, that has that name.

So you can find this by browsing the documentation. I think Thomas showed you how to browse the documentation in Visual Studio. We won't waste time on that. So going back to our event. What I'm going to do is, again, messagebox.show. I'm not going to put anything inside because first I got a resolve the reference for the message box.

And then, what I'm going to put inside is workspace.name, for example, or .filename. And before that, I'm going to add a text you just opened the graph from. And I'm going to put a plus in between them. So what should happen is, if we hook this event up to Dynamo correctly, every time you open a file in Dynamo, this event should get fired which will pop up a message box and tell you, you've just opened the file from this file path, OK?

So let's look at how we actually hook this up to Dynamo. So it actually does something. And to do that, we're going to add a method here called public static void register event handlers. It will want a ready params object as an input. And if I hover over ready params, and I use the light bulb to add using Dynamo.extensions, I can then go params.

Maybe don't use the name params, just use param. Seems like it's a protected keyword. So let's use that. So param.current. And as soon as you start typing current, you'll see the events pop up in Dynamo. So if I backspace a little bit and I click the Thunderbolt icon in Visual Studio, this is the list of all the events that this object is telling me about from Dynamo. So I can react to the current workspace changed, current workspace cleared, which will be fired when you close a file, or when you receive a notification. I've never seen anyone use those in Dynamo though, so we're not going to tackle this.

So I'm going to click on current workspace changed. And we're going to use the same syntax as our clicker. Plus equals on current workspace changed. So what we're saying is, whenever that event gets fired up in Dynamo, also fire up our own event, our own method here. So our method would be called when Dynamo is methods where event fires off, essentially. And I think that's all we really need to do in this event file.

However, if we left it there, we'd basically start having memory leaks. So when you work with events like this and C#, always remember if you've registered an event, you should also unregistered that same event. So to do that, we are going to have to add a private property here. So I'm going to add a private ready params, and I'm going to call it ready params.

And whenever we get called with a register event handlers, I'm going to say this-- actually, I can't use this because it's a static class. But I can use ready params with the event name-- sorry, the class name in front of it. So events.readyparams. It might need to be public not private.

Sorry, I'm blanking out. So if we've made it a static class, we need to make everything inside of it static, right? So we've made a static field up here. So if we call it, now we should see it, and we record the value of param on there. So we can use the same thing below it, or we can use param. They're the same thing at this point.

So what we want is a sister method like this. So I'm going to copy paste the whole thing. I'm just going to add unregistered event handlers. I'm not going to need to keep track of this. And instead of the plus equals, I'm going to go minus equals. So this is basically saying now unregister our method from that event so it no longer fires when these things fire off.

OK, we're done with our event class. This is all ready to be used now. So I'm going to go back to my view extension example. And whenever I'm in loaded, essentially, or actually I can do this in the extension itself, which isn't here anymore. So I will use-- let me see where the ready params are.

OK, I have to actually add my extension back in. So add class extension example. I'm going to do the same I extension. And I will implement it again. Make this public. I will copy paste the GUID from the other one and change one of the digits on there.

So instead of 80 at the end, I go 90. And then, get rid of all of these throws. So I'm just going to call this extension. I don't need to do anything in any of the methods. What I do need to use is this public void ready method. So I'm basically going to connect my events class to Dynamo here.

So what we're going to do is I'm going to call event.registereventhandlers. And you'll remember that it wants ready parameters, so I'm just going to give it the object that Dynamo is giving me. Now, in shut down, I'm going to do the opposite, which is events.unregistereventhandlers. And I will give it-- well, this one actually, if we go to our events class, it shouldn't need any parameters because we already have a reference to that object. So back in our extension, we can just call unregistered even handlers, and it handles that for us.

Anyone not caught up? Do I need to go back to anything? I'm just conscious I've flown through the last bit a little bit. No? OK, so if I press start, what should happen if I've done everything right as Dynamo starts. And if I open a file called desks, I should get notified, but I don't, which probably means that Dynamo.extensionexample.

OK, I don't have a definition of the extension itself. So I'm going to need you guys to right click on the view extension example, copy that file, paste it in the projects, and then rename it, instead of view extension example, it should just say extension definition and without the copy at the end. And if you go inside of it, open that file up, we get rid of view inside of there. So it's just calling the extension example class.

And the last bit, because I wouldn't have shown you this before, is if you right click on this xml file and go to properties, you also have to disable this build action from resource to none. And copy to output directory should be set to copy always. If you don't do this, the xml file won't be copied over with the package, and none of this will fire, which is what happened when I pressed start earlier.

So now, if I press start, this extension should actually be loaded. And if I open a file called desks, I should be getting a notification, and I'm not.

AUDIENCE: Did you inherit some algorithm [INAUDIBLE] copy, [? did you mean ?] [? to take View ?] out of the [INAUDIBLE]?

PRESENTER 1: I did.

AUDIENCE: Where it says [INAUDIBLE] extension [INAUDIBLE].

PRESENTER 1: What, this guy?

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Line one. Ah, yes. Good spot. So if we save and press start again, the examples that I've prepared on GitHub are each for its own topic. So the code we did in the first example didn't carryover, which is why we're having to redo a tiny bit of it. So now when we open desks, finally, we get that notification. You just open the graph, and it gives me the entire file path.

So you can see how you get all of this information from Dynamo. Now, we've got about 20 minutes left. So what I suggest is that we open the completed example of this so you see what we're supposed to get to. And then, I will just show you the UI part at the end so you get to do some of the user interface parts.

So if you open exercise two complete, if we followed all the steps on the Git repository, we would, essentially, be adding one thing to the view extension, which is this inputs view model. Now, this is a fairly long class by the standards of what we did today. What this class does is it gets initialized when the menu item is called or when Dynamo starts our view extension. And it basically keeps track of all the nodes on the canvas, how many connectors, and how many of those are input nodes or marked as inputs.

So this is the class that holds all the data that is necessary for our UI, our user interface, that little window we saw at the beginning, to actually display those statistics. It's also the one that's responsible for notifying our user interface when something changes in Dynamo. You saw our user interface react instantly. This is the class that actually links the two together. Just like Dynamo has view models, we have our own view model.

Now, we won't type this out because it's fairly long. But I will cover what we have inside of it here. We have a dictionary to actually keep track of the input nodes. This is required for that data grid just so we have the name of the node and the value of the-- current value of that node. We have a property that keeps track of the input node names, so just the names of them.

Another property that's a string that keeps track of the node count. And you'll notice this is a string, but it keeps track of a number. It's a string because it needs to be a string for the user interface. So somewhere else in this code we convert that number to a string so that we can display it on the user interface.

OK, the same with wire count. We see that we have a constructor. And it gets the same property ready params that we've been used to now. It resets the statistics, which if I go to that method, just makes everything zero, basically. And then, it registers a bunch of events. So every time a node is added, it registers our own method to handle that change.

Now, if we go to those methods, you'll see that all they do is they call the same method called recompute, which is up here. And this is the one that says, OK, I now have all the objects. Let me actually just count how many nodes there are for each one of them, get the value, put it in the dictionary, actually count the nodes, and make it a string, count the wires. And this is using those same ready parameters that we had earlier, right?

So readyparams.currentworkspacemodel.connectors. We saw it in action earlier. This is where we actually just record the value of it to display for purposes. And then at the end, we just notify our user interface framework that these three properties have changed, so make sure that you update the user interface. Now, view models, like I said before, and-- UI is quite a lot to get into. We can spend a week on this easy.

So feel free to look at the codes when you get home. And if you want to dive into these view models more, and why their notification objects and why things like raising property change events are required, it's a fairly long read, but it is useful in the long run. And that's pretty much all this view model does, right?

And back in the extension example, we're just keeping track of a few more items such as our menu and the view loaded parameters. And then, somewhere in here, we have a method called make and show inputs window, which is us basically initializing that view model from the loaded parameters. And for example, we're just showing a message box here at the minute.

So if I click on start, this exercise doesn't have any UI. So we've just done the view model. I need to re-point it to Dynamo. So I'll do that real quick for you. And we can do the last exercise which is the actual UI bit. So what should happen now is we should have another menu item up in our new dev menu, which should say show stats window or something like that.

And if we have a graph that is open, let's say, the desk one and let's make a number slider. And we right click on this guy and set him to his input. When we show this graph, show input stats, we get a message box that says there are nine total nodes, eight wires, one of these things is marked as an input. So again, the message box isn't the exciting bit. The exciting bit is that we know about all of this data that is inside Dynamo. The message box is just the easiest way to show you guys that we have that data and that we can use it, essentially.

So if we now start the final exercise, we'll add the UI really quickly and you'll see it in all of its glory. OK, so I will close this. And if we go to the data sets and go to the session for extensions, exercise three start. I think we have just about enough time to actually do this.

OK, so here we are back in Visual Studio, right? I am going to expand the input folder. And does everyone have the input folder, and the two files inside of there? Yeah? OK, and I'm going to open input window.xaml. Now, these xaml files are basically the Microsoft Presentation Foundation, a Windows Presentation Foundation way of building user interfaces.

Think about it as HTML, if you're familiar with that. It's a markup language where you declare what your user interface-- what elements it has, and then the framework responsible for taking your code and translating that into an actual visual element. So what you see here is a preview of what that window will look like. It's empty at the minute. And below it, what you see is the code that is generating that window, essentially, which is that the minute is just got some place holder parts to it.

So let's just copy paste some snippets because that will make us go quicker. And you will actually see and understand some of the parts involved in this. So I will scroll all the way down to exercise three. And the first snippet I'm going to copy paste is this bit at the top. And I'm going to copy paste it right under here. Well, actually, I think it's already done.

Yep, it's already done. So we don't need to do that bit. So instead, I'm going to copy the one that says stack panel. So going back to Visual Studio, we have a stack panel here already, so I don't need to do that either. So I'm going to look inside of it. OK, grids go here and data grid goes here. So I know that I'm going to have to deal with the grids, and then I'm going to have to deal with the data grid myself, right?

So I'm going back to my snippets. This is how we actually define a grid. Now, we don't want to copy paste the whole thing because we have the stack panel already. So just select and copy paste the bit that says grid. So from the element that starts with grid to the one that ends with grid.

So if I copy this bit and I put it over in my xaml file here, what this is doing is it's actually just telling it, I have a structure to my user interface. I have two columns. That's what the call them definitions do. And then, I have four rows. And that means that I basically split my user interface in two columns, four rows. So that's 4 by 2. That's eight slots I can use to put elements into.

So the next thing we're going to do-- and we're going to make some element, and assign them to a very specific slot in this grid of ours. So after we've defined the grid, we go back to our snippets. And we can add something called a few text blocks. These are very simple, essentially, text elements. I paste them immediately after the grid. And you'll see the UI updates.

If I scrolled all the way to the beginning, you'll see that I'm basically playing with the column grid here just saying, oh, use the first row and the first column or use the second row and the first column. And I'm just putting these things in the right slots.

So this has just created this label nodes, that is the first text block. The second one is this one, and this one's a bit more interesting because you see here the text of it features this thing called binding. Binding, connected with our view model, is what makes our user interface react to changes. So we don't have to specifically update this text label. We're binding it to the value in the view model, which means that every time the view model gets updated, our UY will pick up that update and actually update itself. So we're linking the two together, and this bit is the tricky bit in WPF and UI, which is why we didn't type out the model portion, OK?

So once these things are binded together they will work. And the last thing we need to do, going back to our snippets, is to actually now trigger this window. Make it happen. Make it appear on the screen, actually. So I will take this snippet and I will save the xaml file. That's all good. I can go back to my view extension example, right? And under make menu items, we already have the menu item for it, so we don't need to do anything there.

We're already making the-- in the make and show input window, we're already making the view model of this. The only bit we're not doing is associating the view model with the actual window, and we're not showing the window. So I'm going to copy paste a snippet for this. So I will just take the entire contents of this method and paste them in, and you'll see the difference here.

So we still make the view model the same way. And then, we make a new instance of our inputs window, which is the xaml file we've been working on. It's a separate class, a separate thing. It's still code. We tell it that the main grid's data context is our view model. So this is the way where you associate your view model, a specific instance of it, to the WPF window, to the UI of it.

So you're telling it this UI is running in the context of this view model. So when we're doing that binding, the name of the property is the name of the property on the view model. And this is the bit that connects the two, essentially. We're also setting the owner of this window so that we don't cause all sorts of nasty behaviors and cause other things to crash. So whenever Dynamo gets closed, this window should also get closed, which is what this is doing.

We're setting the position of the window. Again, optional. It's a nicety. We're just saying, yeah, I'm just going to make sure it's inside the Dynamo window somewhere. And the last thing we do is we actually show this window object, right?

So this method is now all done. If I go back to our menu item, we are already handling the click of this. So I don't need to do anything else. So if I run this-- and I need to update where Dyno is again. Dynamo opens. I'm going to open a graph. And I'm going to click my menu. Show input stats. And you'll see that it's a nice round number. They're both eight. So I have eight nodes on the canvas and eight wires. Let's see what happens if I delete one. We should have seven nodes and six wires, which is what happens. And the nice bit about this is that whatever I do in Dynamo, I can even move this somewhere else. This thing still updates. And that's because those view models in the UI are linked together.

Any questions on that? Do you understand the relationship between the view model and the UI? That's the tricky bit. The WPF itself is tricky, but there's, thankfully, Stack Overflow so you can copy paste lots of things from there. Can you think of any use cases that you might want to use these kind of windows for? Or user interfaces Dynamo?

AUDIENCE: [INAUDIBLE] Dynamo so that we can actually make the [INAUDIBLE] Dynamo that you can a better UI.

PRESENTER 1: Yeah, so one of the latest things that the Dynamo team has done is they've enabled a sidebar panel on the right hand side. So how you have the library on the left, you can have another one on the right hand side. And you can inject your own content in there. So if you want to add new windows and new panels to Dynamo, that's now a lot easier thanks to these additions the Dynamo team has been making.

AUDIENCE: [INAUDIBLE] like a Dynamo UI [INAUDIBLE].

PRESENTER 1: Yeah you could, for example, you could replace the entire Dynamo UI if you wanted. You have the Dynamo model underneath it, and you just make something else that can talk to that. So if you're handy with WPF and UI code, there are actually some graph libraries to visualize these things. Could be a nice little project. Yeah.

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Yes.

AUDIENCE: [INAUDIBLE]

PRESENTER 1: Yeah, so they have all of the styling defined. So you can make it look the same. OK, cool. So the very last bit we need to do is now, actually, display those input nodes, which is what we wanted to do in the first place. And the reason we wanted to do that we could-- like me navigating our generative design graph and keep stock of the inputs stats we still have of the beginning of the graph. To do that, I'm going to need to add the last element to the user interface, which is this data grid. So going back to my snippets.

Let's see, we don't have that. So I'm going to add this new text block. And I'm going to add it underneath all of the other ones. So we should see an input nodes thing appear here. And we are going to, basically, add a data grid at the bottom. I will not type this out because it's fairly long. But if I copy paste and show you what it is, it's a data grid component. And if you're wondering where I'm getting these components from, if I just open the tool box on the left hand side, it initializes for a little bit.

And you go common WPF controls, for example. Here's all the UI elements you could be using, for example. If you go to all of them, there's even more of them. Checkboxes, combo boxes, grids, grid splitters, images, labels, list boxes, whatever you can think of, it's pretty much there. If you don't see it here, you can make your own special controls. But this is just using the data grid from here that's built in.

So you'll see the data grid has appeared here. And the most important part is that the item source property of this data grid is linked to our input nodes property on our view model. So this is what will make our input nodes actually show up in the data grid. And then, the last bit we're doing is we're saying it has two columns, which are actually bound to the key and value of the dictionary we're storing this in.

A little bit of more complicated things happening here, but all this is to say that we are displaying a small data grid. Think of it like an Excel table of the nodes that are in our graph that are marked as input nodes. So if I start Dynamo again, you'll notice that I didn't need to do anything else. Our view model already knows about these things, so I didn't need to update it.

And if I just open our UI, you'll see that has been updated. So if I make a number slider and right click on it and tag it as is input, you'll see nothing changed. This is because we're not actually reacting to an event on the node, or we're not keeping track of node properties being changed.

However, if I plug and unplug something, that will force Dynamo to reassess its status, and we'll get notified of these changes. As homework for you guys, there are ways to subscribe to specific node events. So whenever you add a node to the canvas, you could check, oh, is this an event that produces this kind of-- sorry, is this node one that produces these kind of events? I'll subscribe two events to this particular node. And you do that for every node, and that way you can keep track of nodes.

You can see how that might be consuming, though. So a small limitation like this is something you can probably live with, or you can just add a button here that says re-compute or sync up. So if I copy paste this guy, and I change his value and make sure this is marked as input again, it should basically-- probably because it's also called number slider. Yeah. It shows up in here.

And I think that's pretty much all we have time to do. So what I'm going to show you next is your homework. So we have this limitation that we can't react to nodes. And we have the limitation that that data grid is read only. So where I wanted this to get to, and this is what you can hopefully make it happen when you get home, is you can take that data grid and whenever you click into the cell and type something in, update the value on the node, right?

And if you use the new API in Dynamo that lets you tuck this into the right hand panel, you could be anywhere in the graph and you could be changing your inputs without having to zoom out, go back to the beginning, move the sliders, zoom back out, figure out where you were before, and lose track of things. And that's really it. That's all that we had for extensions.

Hopefully, that was useful. Hopefully, you saw the power of what you could do with extensions. Have a look at the repo. There's links to other ones. Remember the thing we showed you at the beginning where you can control Dynamo through the web if you're interested, or other powerful approaches like that. And let us know what ideas you have for extensions. They're very expressive and very powerful. So I'm keen to see what you guys come up with.

Hope it was a good day. And let's go to the beer bus now, because I think I've held you up enough from that. All right, thank you.

[APPLAUSE]

PRESENTER 3: [INAUDIBLE] thank you for keeping your attention focused here today. We really appreciate you coming out. I just want to give a special thank you to everybody who helped out. [INAUDIBLE] for being our assistants and helping us out.

[APPLAUSE]

______
icon-svg-close-thick

Настройки cookie

Ваша конфиденциальность и оптимизация возможностей работы важны для нас. Мы собираем данные об использовании вами этого сайта с целью адаптации информации и разработки приложений.

Можем ли мы собирать и использовать ваши данные?

Узнайте подробнее о службах сторонних разработчиков., которые мы используем, и нашем заявлении о конфиденциальности.

Обязательные к использованию: требуются для корректной работы нашего сайта и предоставления сервисов

Эти cookie позволяют нам регистрировать ваши предпочтения или информацию о входе в систему, отвечать на ваши запросы или сохранять данные о вашей корзине.

Оптимизация работы: позволят демонстрировать только релевантную информацию

Эти cookie позволят предоставить вам расширенные функциональные возможности и персонализацию. Они могут быть установлены нами или сторонними поставщиками, чьи сервисы мы используем для предоставления информации и персонализации. Если вы не разрешите использование cookie этого типа, некоторые или все сервисы могут оказаться недоступны.

Персонализация рекламы: позволят предлагать вам целевую рекламу

Эти cookie собирают данные о пользователях на основе их действий и интересов, с целью демонстрации релевантных объявлений и отслеживания эффективности. Благодаря им, пользователю будут доступны рекламные материалы, наиболее соответствующие его интересам. Если вы не разрешите использование cookie этого типа, рекламные материалы будут носить менее адресный характер.

icon-svg-close-thick

СЛУЖБЫ СТОРОННИХ РАЗРАБОТЧИКОВ

Узнайте подробнее о службах сторонних разработчиков, которые мы используем для каждой категории, и получите сведения о том, как мы используем данные, которые собрали о вас в интернете.

icon-svg-hide-thick

icon-svg-show-thick

Обязательные к использованию: требуются для корректной работы нашего сайта и предоставления сервисов

Qualtrics
Мы используем Qualtrics для обеспечения обратной связи с клиентами через опросы или онлайн-формы. Вас могут выбрать случайно для участия в опросе или вы можете самостоятельно решить оставить отзыв. Чтобы лучше понять ваш опыт работы с нами, перед заполнением опроса мы собираем данные о ваших действиях. Это помогает нам решить проблемы, с которыми вы могли столкнуться. Политика конфиденциальности Qualtrics
Akamai mPulse
Для сбора данных о поведении клиентов на наших сайтах мы используем Akamai mPulse. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Akamai mPulse
Digital River
Для сбора данных о поведении клиентов на наших сайтах мы используем Digital River. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Digital River
Dynatrace
Для сбора данных о поведении клиентов на наших сайтах мы используем Dynatrace. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Dynatrace
Khoros
Для сбора данных о поведении клиентов на наших сайтах мы используем Khoros. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Khoros
Launch Darkly
Для сбора данных о поведении клиентов на наших сайтах мы используем Launch Darkly. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Launch Darkly
New Relic
Для сбора данных о поведении клиентов на наших сайтах мы используем New Relic. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности New Relic
Salesforce Live Agent
Для сбора данных о поведении клиентов на наших сайтах мы используем Salesforce Live Agent. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Salesforce Live Agent
Wistia
Для сбора данных о поведении клиентов на наших сайтах мы используем Wistia. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Wistia
Tealium
Для сбора данных о поведении клиентов на наших сайтах мы используем Tealium. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Tealium
Upsellit
Для сбора данных о поведении клиентов на наших сайтах мы используем Upsellit. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Upsellit
CJ Affiliates
Для сбора данных о поведении клиентов на наших сайтах мы используем CJ Affiliates. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности CJ Affiliates
Commission Factory
Для сбора данных о поведении клиентов на наших сайтах мы используем Commission Factory. Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Commission Factory
Google Analytics (Strictly Necessary)
Для сбора данных о поведении клиентов на наших сайтах мы используем Google Analytics (Strictly Necessary). Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Google Analytics (Strictly Necessary)
Typepad Stats
Для сбора данных о поведении клиентов на наших сайтах мы используем Typepad Stats. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Typepad Stats
Geo Targetly
Мы используем Geo Targetly, чтобы направлять посетителей сайта на наиболее подходящие веб-страницы и/или показывать контент, подобран-ный с учетом их местоположения. Geo Targetly определяет местоположение посетителя сайта по IP-адресу его устройства. Таким образом на сайте (с большой вероятностью) отображается контент на языке региона пользователя.Политика конфиденциальности Geo Targetly
SpeedCurve
Мы используем SpeedCurve для мониторинга и определения производительности вашего веб-сайта путем измерения времени загрузки веб-страницы, а также отклика последующих элементов, таких как изображения, сценарии и текст.Политика конфиденциальности SpeedCurve
Qualified
Qualified is the Autodesk Live Chat agent platform. This platform provides services to allow our customers to communicate in real-time with Autodesk support. We may collect unique ID for specific browser sessions during a chat. Qualified Privacy Policy

icon-svg-hide-thick

icon-svg-show-thick

Оптимизация работы: позволят демонстрировать только релевантную информацию

Google Optimize
Мы используем Google Optimize для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Google Optimize
ClickTale
Мы используем ClickTale, чтобы получить представление о трудностях, с которыми вы можете столкнуться на наших сайтах. Мы используем записи сеансов, чтобы узнать, как вы взаимодействуете с нашими сайтами, включая все элементы страниц. Ваша личная информация скрыта и не собирается. Политика конфиденциальности ClickTale
OneSignal
Мы используем OneSignal для развертывания цифровой рекламы на сайтах, поддерживаемых OneSignal. Реклама основывается на данных OneSignal и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными OneSignal от клиентов. Мы используем данные, которые предоставляем OneSignal, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности OneSignal
Optimizely
Мы используем Optimizely для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Optimizely
Amplitude
Мы используем Amplitude для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Amplitude
Snowplow
Для сбора данных о поведении клиентов на наших сайтах мы используем Snowplow. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Snowplow
UserVoice
Для сбора данных о поведении клиентов на наших сайтах мы используем UserVoice. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности UserVoice
Clearbit
Služba Clearbit umožňuje doplňování dat v reálném čase za účelem poskytování individuálního a relevantního prostředí pro naše zákazníky. Mezi data, která shromažďujeme, mohou patřit vámi navštívené stránky, aktivované zkušební verze, přehraná videa, provedené nákupy a vaše IP adresa nebo ID zařízení. Политика конфиденциальности Clearbit
YouTube
YouTube — платформа для обмена видеороликами, через которую пользователи могут просматривать и размещать встроенные видеоролики на наших веб-сайтах. YouTube предоставляет данные о зрительской аудитории. Политика конфиденциальности YouTube

icon-svg-hide-thick

icon-svg-show-thick

Персонализация рекламы: позволят предлагать вам целевую рекламу

Adobe Analytics
Для сбора данных о поведении клиентов на наших сайтах мы используем Adobe Analytics. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса или идентификаторы устройств, а также учетные записи Autodesk. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Adobe Analytics
Google Analytics (Web Analytics)
Для сбора данных о поведении клиентов на наших сайтах мы используем Google Analytics (Web Analytics). Это могут быть посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Мы используем эти данные для оценки работы нашего сайта, а также удобства его использования. Они помогают нам улучшить предоставляемые возможности. Кроме того, мы используем передовые методы анализа для оптимизации работы с электронной почтой, поддержкой клиентов и отделом продаж. Политика конфиденциальности Google Analytics (Web Analytics)
AdWords
Мы используем AdWords для развертывания цифровой рекламы на сайтах, поддерживаемых AdWords. Реклама основывается на данных AdWords и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными AdWords от клиентов. Мы используем данные, которые предоставляем AdWords, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности AdWords
Marketo
Мы используем Marketo для своевременной отправки более актуальных сообщений клиентам по электронной почте. Для этого мы собираем данные о вашем поведении в интернете и взаимодействии с отправляемыми нами сообщениями электронной почты. Данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, коэффициенты открытия сообщений электронной почты, сведения о переходах по ссылкам и др. Мы можем объединять эти данные с данными, полученными из других источников, чтобы оптимизировать ваш опыт работы с отделом продаж или службой технической поддержки, а также предлагать более подходящие материалы на основании использования передовых средств анализа данных. Политика конфиденциальности Marketo
Doubleclick
Мы используем Doubleclick для развертывания цифровой рекламы на сайтах, поддерживаемых Doubleclick. Реклама основывается на данных Doubleclick и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Doubleclick от клиентов. Мы используем данные, которые предоставляем Doubleclick, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Doubleclick
HubSpot
Мы используем HubSpot для своевременной отправки более актуальных сообщений клиентам по электронной почте. Для этого мы собираем данные о вашем поведении в интернете и взаимодействии с отправляемыми нами сообщениями электронной почты. Данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, коэффициенты открытия сообщений электронной почты, сведения о переходах по ссылкам и др. Политика конфиденциальности HubSpot
Twitter
Мы используем Twitter для развертывания цифровой рекламы на сайтах, поддерживаемых Twitter. Реклама основывается на данных Twitter и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Twitter от клиентов. Мы используем данные, которые предоставляем Twitter, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Twitter
Facebook
Мы используем Facebook для развертывания цифровой рекламы на сайтах, поддерживаемых Facebook. Реклама основывается на данных Facebook и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Facebook от клиентов. Мы используем данные, которые предоставляем Facebook, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Facebook
LinkedIn
Мы используем LinkedIn для развертывания цифровой рекламы на сайтах, поддерживаемых LinkedIn. Реклама основывается на данных LinkedIn и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными LinkedIn от клиентов. Мы используем данные, которые предоставляем LinkedIn, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности LinkedIn
Yahoo! Japan
Мы используем Yahoo! Japan для развертывания цифровой рекламы на сайтах, поддерживаемых Yahoo! Japan. Реклама основывается на данных Yahoo! Japan и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Yahoo! Japan от клиентов. Мы используем данные, которые предоставляем Yahoo! Japan, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Yahoo! Japan
Naver
Мы используем Naver для развертывания цифровой рекламы на сайтах, поддерживаемых Naver. Реклама основывается на данных Naver и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Naver от клиентов. Мы используем данные, которые предоставляем Naver, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Naver
Quantcast
Мы используем Quantcast для развертывания цифровой рекламы на сайтах, поддерживаемых Quantcast. Реклама основывается на данных Quantcast и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Quantcast от клиентов. Мы используем данные, которые предоставляем Quantcast, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Quantcast
Call Tracking
Мы используем Call Tracking для предоставления адаптированных телефонных номеров для наших рекламных кампаний. При этом вы получаете быстрый доступ к нашим агентам, а мы можем получить более точную оценку своей работы. Мы можем собирать данные о вашем поведении на наших сайтах на основе предоставленного телефонного номера. Политика конфиденциальности Call Tracking
Wunderkind
Мы используем Wunderkind для развертывания цифровой рекламы на сайтах, поддерживаемых Wunderkind. Реклама основывается на данных Wunderkind и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Wunderkind от клиентов. Мы используем данные, которые предоставляем Wunderkind, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Wunderkind
ADC Media
Мы используем ADC Media для развертывания цифровой рекламы на сайтах, поддерживаемых ADC Media. Реклама основывается на данных ADC Media и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными ADC Media от клиентов. Мы используем данные, которые предоставляем ADC Media, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности ADC Media
AgrantSEM
Мы используем AgrantSEM для развертывания цифровой рекламы на сайтах, поддерживаемых AgrantSEM. Реклама основывается на данных AgrantSEM и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными AgrantSEM от клиентов. Мы используем данные, которые предоставляем AgrantSEM, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности AgrantSEM
Bidtellect
Мы используем Bidtellect для развертывания цифровой рекламы на сайтах, поддерживаемых Bidtellect. Реклама основывается на данных Bidtellect и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Bidtellect от клиентов. Мы используем данные, которые предоставляем Bidtellect, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Bidtellect
Bing
Мы используем Bing для развертывания цифровой рекламы на сайтах, поддерживаемых Bing. Реклама основывается на данных Bing и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Bing от клиентов. Мы используем данные, которые предоставляем Bing, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Bing
G2Crowd
Мы используем G2Crowd для развертывания цифровой рекламы на сайтах, поддерживаемых G2Crowd. Реклама основывается на данных G2Crowd и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными G2Crowd от клиентов. Мы используем данные, которые предоставляем G2Crowd, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности G2Crowd
NMPI Display
Мы используем NMPI Display для развертывания цифровой рекламы на сайтах, поддерживаемых NMPI Display. Реклама основывается на данных NMPI Display и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными NMPI Display от клиентов. Мы используем данные, которые предоставляем NMPI Display, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности NMPI Display
VK
Мы используем VK для развертывания цифровой рекламы на сайтах, поддерживаемых VK. Реклама основывается на данных VK и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными VK от клиентов. Мы используем данные, которые предоставляем VK, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности VK
Adobe Target
Мы используем Adobe Target для тестирования новых возможностей наших сайтов и их адаптации в соответствии с вашими потребностями. Для этого пока вы работаете с сайтами, мы собираем данные поведения. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, IP-адреса, идентификаторы устройств, учетные записи Autodesk и прочее. На основании тестирования возможностей изменяются версии сайтов. Кроме того, на основе атрибутов посетителей на сайтах появляется персонализированный контент. Политика конфиденциальности Adobe Target
Google Analytics (Advertising)
Мы используем Google Analytics (Advertising) для развертывания цифровой рекламы на сайтах, поддерживаемых Google Analytics (Advertising). Реклама основывается на данных Google Analytics (Advertising) и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Google Analytics (Advertising) от клиентов. Мы используем данные, которые предоставляем Google Analytics (Advertising), для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Google Analytics (Advertising)
Trendkite
Мы используем Trendkite для развертывания цифровой рекламы на сайтах, поддерживаемых Trendkite. Реклама основывается на данных Trendkite и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Trendkite от клиентов. Мы используем данные, которые предоставляем Trendkite, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Trendkite
Hotjar
Мы используем Hotjar для развертывания цифровой рекламы на сайтах, поддерживаемых Hotjar. Реклама основывается на данных Hotjar и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Hotjar от клиентов. Мы используем данные, которые предоставляем Hotjar, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Hotjar
6 Sense
Мы используем 6 Sense для развертывания цифровой рекламы на сайтах, поддерживаемых 6 Sense. Реклама основывается на данных 6 Sense и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными 6 Sense от клиентов. Мы используем данные, которые предоставляем 6 Sense, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности 6 Sense
Terminus
Мы используем Terminus для развертывания цифровой рекламы на сайтах, поддерживаемых Terminus. Реклама основывается на данных Terminus и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными Terminus от клиентов. Мы используем данные, которые предоставляем Terminus, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности Terminus
StackAdapt
Мы используем StackAdapt для развертывания цифровой рекламы на сайтах, поддерживаемых StackAdapt. Реклама основывается на данных StackAdapt и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными StackAdapt от клиентов. Мы используем данные, которые предоставляем StackAdapt, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности StackAdapt
The Trade Desk
Мы используем The Trade Desk для развертывания цифровой рекламы на сайтах, поддерживаемых The Trade Desk. Реклама основывается на данных The Trade Desk и данных поведения, которые мы собираем в процессе работы клиентов с нашими сайтами. Такие данные могут включать посещенные страницы, запущенные пробные версии, воспроизведенные видеоролики, совершенные покупки, а также IP-адреса или идентификаторы устройств. Эта информация может объединяться с данными, полученными The Trade Desk от клиентов. Мы используем данные, которые предоставляем The Trade Desk, для лучшей адаптации цифровой рекламы и предоставления наиболее актуальных рекламных материалов. Политика конфиденциальности The Trade Desk
RollWorks
We use RollWorks to deploy digital advertising on sites supported by RollWorks. Ads are based on both RollWorks data and behavioral data that we collect while you’re on our sites. The data we collect may include pages you’ve visited, trials you’ve initiated, videos you’ve played, purchases you’ve made, and your IP address or device ID. This information may be combined with data that RollWorks has collected from you. We use the data that we provide to RollWorks to better customize your digital advertising experience and present you with more relevant ads. RollWorks Privacy Policy

Вы уверены, что не хотите узнать обо всех возможностях работы с нашими службами в интернете?

Мы хотим, чтобы вам было комфортно работать с нами. Если вы выберете «Да» для категорий на предыдущем экране, мы будем собирать и использовать ваши данные для адаптации возможностей работы и оптимизации приложений. Настройки можно изменить в любой момент, посетив страницу заявления о конфиденциальности.

Удобство работы зависит от вас.

Мы заботимся о вашей конфиденциальности. Собираемые данные помогают нам понять, как вы используете наши продукты, какая информация может вас заинтересовать, а также, что можно изменить для улучшения вашего взаимодействия с компанией Autodesk.

Можем ли мы собирать и использовать ваши данные для адаптации возможностей работы?

Ознакомьтесь с преимуществами адаптированных возможностей работы благодаря управлению параметрами конфиденциальности для этого сайта или перейдите к нашему заявлению о конфиденциальности, чтобы узнать больше о возможных вариантах.