JacquesLucke / blender_vscode

Visual Studio Code extension for Blender development.
MIT License
540 stars 70 forks source link

Fix for #135 bpy.context.[active_]object set to None after adding primitive when run from VS Code Extension #138

Closed CGArtPython closed 1 year ago

CGArtPython commented 1 year ago

Summary of issue

Calling a script via operator results in an empty context.

Related devtalk.blender

from @JacquesLucke https://devtalk.blender.org/t/how-to-run-a-script-from-outside-blender-script-live-link-addon/9792/3?u=jacqueslucke

Solution

Use bpy.app.timers to register a function to run the target script.

Changes

pythonFiles\include\blender_vscode\operators\script_runner.py

Potentially related issues

Testing

CGArtPython commented 1 year ago

Ready to make any changes based on the code review.

I can also move this code out of the operator's folder since it no longer contains the operator.

CGArtPython commented 1 year ago

I was just looking into the issue and it seems like the proposed fix does not work generally. It essentially removes the context-overrides created by prepare_script_context. This happens to fix your script but can break other code. For example, see what happens when you print bpy.context.space_data in the script: In master this prints the 3d view space, but with this patch the result is None.

I think the core issue for what causes the issue in #135 is that the context changes while the script is executed and the context-override is not valid anymore. The diff below also seems to fix the bug for me, maybe you can try that as well. The idea is that we only override the "important" part of the context, and leave the rest for Blender to figure out when actually accessing e.g bpy.context.active_object.

diff --git a/pythonFiles/include/blender_vscode/operators/script_runner.py b/pythonFiles/include/blender_vscode/operators/script_runner.py
index 9159b90..a1d022d 100644
--- a/pythonFiles/include/blender_vscode/operators/script_runner.py
+++ b/pythonFiles/include/blender_vscode/operators/script_runner.py
@@ -42,16 +42,8 @@ def prepare_script_context(filepath):
     context["view_layer"] = context["window"].view_layer
     context["screen"] = context["window"].screen
     context["workspace"] = context["window"].workspace
-    context["active_object"] = context["view_layer"].objects.active
-    context["object"] = context["active_object"]
-    context["collection"] = context["view_layer"].active_layer_collection.collection
     context["area"] = get_area_by_type(area_type)
-    context["space_data"] = context["area"].spaces.active
-    context["selected_objects"] = [obj for obj in context["view_layer"].objects if obj.select_get(view_layer=context["view_layer"])]
-    context["selected_editable_objects"] = context["selected_objects"]
     context["region"] = get_region_in_area(context["area"], region_type) if context["area"] else None
-    if context["space_data"].type == "VIEW_3D":
-        context["region_data"] = context["space_data"].region_3d
     return context

 def get_area_by_type(area_type):

You are right! Just tested one of my scripts that use context.space_data, and that script failed with my change.

I tested it with my scripts, and it looks like everything is working!

I can close this PR. Would you be able to submit your fix?

JacquesLucke commented 1 year ago

I committed the alternative fix in 621e275d9000e571f4b4d10cbde7abdd1cf15e0a.