Blender-Pipeline/wiki/docs/Story-Editor.md

131 lines
No EOL
13 KiB
Markdown

# Story Editor
There could be confusion with [Script Writer](../../wiki/docs/Script-Writer.md).
Story Editor is the Note Editor for story organization. It's a 2D world of your project. Think about an infinitely large Desktop but only for things in the project. With an ability to plot story lines.
![](https://notabug.org/jyamihud/update_manager/raw/master/vcstudio/51.png)
### Chapters:
- [User Guide](#user-guide)
- [Source Code](#source-code)
# User Guide
I would love to start explaining the large middle part of it. But you would get lost on your project since it's probably empty for you. So instead I gonna go over the various buttons around the main view. So you could start building your story. And then as it goes. I gonna explain the reasons for each thing. And how to use them.
In the top you can see the Analytics progress bar. Starting with ![](../../settings/themes/OldSchool/icons/analytics.png) icon. This is a button that will give you [analytics](../../wiki/docs/Analytics.md) about the project. More about this in the Analytics page. Then you have the ![](../../settings/themes/OldSchool/icons/schedule.png) icon. Followed by the currently scheduled task. It will get you to an asset or a scene in which the task should be done.
For those of you who want to use VCStudio without building a story. But just to organize assets. In he right side you can see the following 4 icons.
![](../../settings/themes/OldSchool/icons/chr.png), ![](../../settings/themes/OldSchool/icons/veh.png), ![](../../settings/themes/OldSchool/icons/loc.png) and ![](../../settings/themes/OldSchool/icons/obj.png)
These are the folders for various types of assets. I didn't want vehicles and characters to be piled up in the same folder. So you have different folders for Characters, Vehicles, Locations and Other Assets.
Looking little below it ![](../../settings/themes/OldSchool/icons/mus.png) is a folder for music and sound effects. And at the very bottom ![](../../settings/themes/OldSchool/icons/folder.png) opens the project's folder.
On the left you can see a set of icons too. So let's go over them too.
![](../../settings/themes/OldSchool/icons/scene_new.png) adds a new Scene node to the Story Editor Space. There are 2 nodes already in the scene. They are marked Red usually. And have the titles of `Start` and `End`. If you used the Blender's node editor. There is usually an input node and an output node. Story also has a start and the end.
So in order to have a story you need to connect the `Start` node to the first scene node. And the first scene node to the second scene node. And this way through all the story. The last scene connect to the `End` node.
If any scene will be out of this "Main Chain" it will not be recognized by the Analytics. So you can have multiple drafts of any scene. And have testing scenes. And they will not effect the main story.
To enter the scene double click it.
![](../../settings/themes/OldSchool/icons/obj_link.png) will create a link to an asset inside the Story Editor space.
![](../../settings/themes/OldSchool/icons/file_link.png) will create a link to a file inside the Story Editor space.
Now you probably gonna see that some files have an output dot. And the Assets links have input dots. These are meant for copying files into different asset's folders.
![](../../settings/themes/OldSchool/icons/blender.png) Main Asset's folder. Meant for Blend Files.
![](../../settings/themes/OldSchool/icons/idea.png) References folder.
![](../../settings/themes/OldSchool/icons/texture.png) Textures folder.
![](../../settings/themes/OldSchool/icons/render.png) Renders folder.
They are also buttons. Clicking on which will give you to link a file **from** such a folder. Dragging the file into a dot like this will **copy** that file over to the other folder. I was considering linking the file. But I ended up using this feature to copy over textures that I will re-paint somewhat for a different asset.
![](../../settings/themes/OldSchool/icons/pin.png) is a feature to organize the Story Editor space. It's a marking tool to mark a place so at any moment you could go to that place by clicking on it's icon. They never go off screen. They stay on the edges of the screen at all times. Making them handy.
![](../../settings/themes/OldSchool/icons/event.png) is a feature to visually group together various elements in the Story Editor Space. Select a few elements and press this button to make a box around them. It's just a visual thing. It's similar to Frames in Blender's Node editor.
![](../../settings/themes/OldSchool/icons/render.png) is a list of currently active animation renders. You set them up from with in the scenes.
![](../../settings/themes/OldSchool/icons/vse.png) is a list if Blend-files for video editing. Blender contains a [very powerful Video Editor](https://docs.blender.org/manual/en/latest/video_editing/introduction.html) built in. I'm using it for the editing of my movies.
![](../../settings/themes/OldSchool/icons/multiuser.png) is the MultiUser window. It's used when you have more then one computer on the project.
![](../../settings/themes/OldSchool/icons/settings.png) is the settings dialogue.
The following chapter is not scary. Source code is not scary. It's Free Software here. You are free to educate yourself.
# Source Code
The best documentation is to read the code of the software directly. For the story editor I recommend:
- [studio/story.py](../../studio/story.py) Reads, Writes and does various things with the story file.
- [studio/studio_storyLayer.py](../../studio/studio_storyLayer.py) Draws the complex story editor thing with all the selections and stuff.
- [studio/studio_nodes.py](../../studio/studio_nodes.py) Draws all the various types of nodes, dots and connection between dots. Contains some of the logic.
**Is there any difference between Project Manager and Story Editor?**
Yes. If you look closely at [project_manager/pm_gtk.py](../../project_manager/pm_gtk.py) and [studio/studio_gtk.py](../../studio/studio_gtk.py) you can see that most of the code is the same. But some stuff is different. Mainly because inside of the project I use a lot more stuff. A lot more rendering logic. That is just not necessary in a simple project chooser.
For example. When rendering windows on top of the main layer in project manager I still draw the main layer on each frame. Then the [blur()](../../UI/UI_elements.py) is applied to it. Then the top layer is drawn.
To do the same inside the project when the main layer is the story editor is quite computationally expensive. In other words. It's slow. So when the current layer is not story editor. I'm not redrawing the story editor. I cash the last frame it drawn and add the `blur()` on top of the cashed version.
You can see it in action by resizing the window while something is drawn on top. In the Project Manager the background will resize with the window. In the studio the background will stay the same and be cut off.
Of course there are other little things like variables for project's analytics, story and other logic related to it.
**How do you draw the nodes?**
Short answer [read this.](../../studio/studio_nodes.py) Long answer: It's complicated. There is a block of data inside the `win` object. Which is actually the `Gtk.Window()` object. I just used the ability to assign variables to it in order to have some truly global variables. For example `win.current` and `win.previous` are all the variables that I might need to compare between 2 frames. Like for example the key presses are stored in `keys` in `win.current`. And I can know what keys were pressed on previous frame by looking in `keys` in `win.previous`.
But there are also things like `win.story` for example. This variable contains a very large dictionary. You can look at the `/pln/story.vcss` file to see what I mean. ( It's secretly a JSON file. ) This dictionary contains an entire data-base of every item in the story editor space. Names, link-types, coordinates, sizes. Everything is there. For scene. The entire scene text is also there.
To draw the nodes I iterate over for example `scenes` in `win.story` and read what name and where each is should be drawn. And send this data to the [studio/studio_nodes.py](../../studio/studio_nodes.py). But I have to always add the `camera` in `win.story` to every coordinate. Or else travelling through the story space will not be possible. Everything will just stay static.
**How do connections between nodes work?**
There is a variable called `arrows` in `win.story` which stores data of connections between 2 nodes. Each node has an input and an output dot. They are rendered using the same [node_dot()](../../studio/studio_nodes.py) function. But the function is very complex. Basically if it's an output node it will record it's position on the screen into a variable called `win.out_dots` and when an input node comes by. It will look through the `arrows` in `win.story` see if it's connected to anything. See if this anything is in `win.out_dots`. And if yes. Draws a line.
Sometimes tho it finds the output dot after the input dot. And when this happens you can see slight disjointedness when traveling in the Story Editor Space.
For the logic of dragging one into another think about both of them being little tiny buttons. If you press on the output dot it will start a special operation with it's coordinates and some metadata. And if you press the input button while this operation is running. This input dot will add an instance into `arrows` in `win.story` using it's own metadata and the metadata of the output node that started the operation. It's a bit simplified. So if you want to know **exactly** how it works. Just read the [node_dot()](../../studio/studio_nodes.py) function.
**How do events change their shape with the contents inside?**
I'm using for this a little function called [rectangle_surround() from UI/UI_math.py](../../UI/UI_math.py). And simplified explanation will be... There is a global variable. Some kind of list of 4 coordinates `X, Y, SizeX, SizeY`. This will represent either the event box. Or the selection box. Or anything like this. And you add to the function each coordinate of everything inside this box. You compare whether one is already inside the other or not. And if the thing that should be inside actually outside. We move the coordinate of the surrounding box out a little to include that object.
Now keep in mind that this is all done before a single frame is rendered and presented to the user. So from the user's perspective the surrounding box always outside of the items. But behind the scenes there were few iterations before it was outside **all** of the items.
**How does collision of 2 rectangles work for the selection?**
In order to detect intersection. Or collision of 2 rectangles I use a very primitive method. Look at [rectangle_overlap() from UI/UI_math.py](../../UI/UI_math.py). Basically I'm checking two 1D lines for intersecting. The `X` axis of both rectangles and the `Y` axis of both rectangles. Look at [line_overlap() from UI/UI_math.py](../../UI/UI_math.py).
I could use some math to check how far the intersection is. But I found it to be unnecessary in this application. ( Maybe I will do it eventually ). So the idea is to check whether first point of the line 0 is anywhere between the points of the line 1. If yes. Detected. If not. Check the second point. If not yet. Swap the lines and do another 2 checks. So at most for 2 rectangles I'm checking 8 times.
**Are images read from the file each time?**
No. They are not. Look at [image() and loadimage() from /UI/UI_elements.py](../../UI/UI_elements.py). There is a global variable `win.images` which is a dictionary of various cario surfaces. Cashed 1 time from the image files. For each cell in the dictionary. Basically the function `image()` is called. A filename is given to it. It looks into the dictionary and checks whether this image is there already in the given cell or not. If not. It loads the image. If yes it draws the image.
Now for images from the internet. Like ones used in the documentation. It's also checking if `auto_download_images` is True or False in the [settings file.](../../settings/settings.data). If it's False it will give user a button to click. Only if a button is clicked, it will download the image and load it into the cell.
The cells are used to have multiple sizes of the same images rendered for different purposes. Like a cell for menu previews. And the cell for big images in the text. And so on. If there would be only one cell. And let's say you loaded the bigger picture first. It would not load it again for another size. It will just render the one already there. Which is not cool.
# Help The Documentation
The documentation files are not perfect. And need maintenance.
*If you are reading it from the VCStudio build in Documentation:*
- Press ![](../../settings/themes/OldSchool/icons/edit.png) to edit locally.
- Press ![](../../settings/themes/OldSchool/icons/notabug.png) to commit in our NotABug repository.
*(C) J.Y.Amihud 2021. Under GPL v3 or later.*