Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
B
blender-addons
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
blender
blender-addons
Commits
aa2e8a2a
Commit
aa2e8a2a
authored
6 years ago
by
Rainer Trummer
Committed by
Jacques Lucke
6 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Port 'Edit Linked Library' addon to Blender 2.8
Differential Revision:
https://developer.blender.org/D4070
parent
96d48401
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
object_edit_linked.py
+87
-66
87 additions, 66 deletions
object_edit_linked.py
with
87 additions
and
66 deletions
object_edit_linked.py
+
87
−
66
View file @
aa2e8a2a
...
@@ -19,21 +19,24 @@
...
@@ -19,21 +19,24 @@
bl_info
=
{
bl_info
=
{
"
name
"
:
"
Edit Linked Library
"
,
"
name
"
:
"
Edit Linked Library
"
,
"
author
"
:
"
Jason van Gumster (Fweeb), Bassam Kurdali, Pablo Vazquez
"
,
"
author
"
:
"
Jason van Gumster (Fweeb), Bassam Kurdali, Pablo Vazquez
, Rainer Trummer
"
,
"
version
"
:
(
0
,
8
,
1
),
"
version
"
:
(
0
,
9
,
1
),
"
blender
"
:
(
2
,
74
,
0
),
"
blender
"
:
(
2
,
80
,
0
),
"
location
"
:
"
View3D > Toolshelf
> Edit Linked Library
"
,
"
location
"
:
"
File > External Data
> Edit Linked Library
"
,
"
description
"
:
"
Allows editing of objects linked from a .blend library.
"
,
"
description
"
:
"
Allows editing of objects linked from a .blend library.
"
,
"
wiki_url
"
:
"
http://wiki.blender.org/index.php/Extensions:2.6/Py/
"
"
wiki_url
"
:
"
http://wiki.blender.org/index.php/Extensions:2.6/Py/
"
"
Scripts/Object/Edit_Linked_Library
"
,
"
Scripts/Object/Edit_Linked_Library
"
,
"
category
"
:
"
Object
"
,
"
category
"
:
"
Object
"
,
}
}
import
bpy
import
bpy
from
bpy.app.handlers
import
persistent
import
logging
import
os
import
os
from
bpy.app.handlers
import
persistent
logger
=
logging
.
getLogger
(
'
object_edit_linked
'
)
settings
=
{
settings
=
{
"
original_file
"
:
""
,
"
original_file
"
:
""
,
"
linked_file
"
:
""
,
"
linked_file
"
:
""
,
...
@@ -42,15 +45,15 @@ settings = {
...
@@ -42,15 +45,15 @@ settings = {
@persistent
@persistent
def
linked_file_check
(
context
):
def
linked_file_check
(
context
:
bpy
.
context
):
if
settings
[
"
linked_file
"
]
!=
""
:
if
settings
[
"
linked_file
"
]
!=
""
:
if
os
.
path
.
samefile
(
settings
[
"
linked_file
"
],
bpy
.
data
.
filepath
):
if
os
.
path
.
samefile
(
settings
[
"
linked_file
"
],
bpy
.
data
.
filepath
):
print
(
"
Editing a linked library.
"
)
logger
.
info
(
"
Editing a linked library.
"
)
bpy
.
ops
.
object
.
select_all
(
action
=
'
DESELECT
'
)
bpy
.
ops
.
object
.
select_all
(
action
=
'
DESELECT
'
)
for
ob_name
in
settings
[
"
linked_objects
"
]:
for
ob_name
in
settings
[
"
linked_objects
"
]:
bpy
.
data
.
objects
[
ob_name
].
select
=
True
# XXX Assumes selected object is in the active scene
bpy
.
data
.
objects
[
ob_name
].
select
_set
(
True
)
# XXX Assumes selected object is in the active scene
if
len
(
settings
[
"
linked_objects
"
])
==
1
:
if
len
(
settings
[
"
linked_objects
"
])
==
1
:
bpy
.
context
.
scene
.
objects
.
active
=
bpy
.
data
.
objects
[
settings
[
"
linked_objects
"
][
0
]]
context
.
view_layer
.
objects
.
active
=
bpy
.
data
.
objects
[
settings
[
"
linked_objects
"
][
0
]]
else
:
else
:
# For some reason, the linked editing session ended
# For some reason, the linked editing session ended
# (failed to find a file or opened a different file
# (failed to find a file or opened a different file
...
@@ -59,32 +62,30 @@ def linked_file_check(context):
...
@@ -59,32 +62,30 @@ def linked_file_check(context):
settings
[
"
linked_file
"
]
=
""
settings
[
"
linked_file
"
]
=
""
class
EditLinked
(
bpy
.
types
.
Operator
):
class
OBJECT_OT_
EditLinked
(
bpy
.
types
.
Operator
):
"""
Edit Linked Library
"""
"""
Edit Linked Library
"""
bl_idname
=
"
object.edit_linked
"
bl_idname
=
"
object.edit_linked
"
bl_label
=
"
Edit Linked Library
"
bl_label
=
"
Edit Linked Library
"
use_autosave
=
bpy
.
props
.
BoolProperty
(
use_autosave
:
bpy
.
props
.
BoolProperty
(
name
=
"
Autosave
"
,
name
=
"
Autosave
"
,
description
=
"
Save the current file before opening the linked library
"
,
description
=
"
Save the current file before opening the linked library
"
,
default
=
True
)
default
=
True
)
use_instance
=
bpy
.
props
.
BoolProperty
(
use_instance
:
bpy
.
props
.
BoolProperty
(
name
=
"
New Blender Instance
"
,
name
=
"
New Blender Instance
"
,
description
=
"
Open in a new Blender instance
"
,
description
=
"
Open in a new Blender instance
"
,
default
=
False
)
default
=
False
)
@classmethod
@classmethod
def
poll
(
cls
,
context
):
def
poll
(
cls
,
context
:
bpy
.
context
):
return
settings
[
"
original_file
"
]
==
""
and
context
.
active_object
is
not
None
and
(
return
settings
[
"
original_file
"
]
==
""
and
context
.
active_object
is
not
None
and
(
(
context
.
active_object
.
instance_collection
and
(
context
.
active_object
.
instance_collection
and
context
.
active_object
.
instance_collection
.
library
is
not
None
)
or
context
.
active_object
.
instance_collection
.
library
is
not
None
)
or
(
context
.
active_object
.
proxy
and
(
context
.
active_object
.
proxy
and
context
.
active_object
.
proxy
.
library
is
not
None
)
or
context
.
active_object
.
proxy
.
library
is
not
None
)
or
context
.
active_object
.
library
is
not
None
)
context
.
active_object
.
library
is
not
None
)
#return context.active_object is not None
def
execute
(
self
,
context
):
def
execute
(
self
,
context
:
bpy
.
context
):
#print(bpy.context.active_object.library)
target
=
context
.
active_object
target
=
context
.
active_object
if
target
.
instance_collection
and
target
.
instance_collection
.
library
:
if
target
.
instance_collection
and
target
.
instance_collection
.
library
:
...
@@ -99,7 +100,7 @@ class EditLinked(bpy.types.Operator):
...
@@ -99,7 +100,7 @@ class EditLinked(bpy.types.Operator):
settings
[
"
linked_objects
"
].
append
(
target
.
name
)
settings
[
"
linked_objects
"
].
append
(
target
.
name
)
if
targetpath
:
if
targetpath
:
print
(
target
.
name
+
"
is linked to
"
+
targetpath
)
logger
.
debug
(
target
.
name
+
"
is linked to
"
+
targetpath
)
if
self
.
use_autosave
:
if
self
.
use_autosave
:
if
not
bpy
.
data
.
filepath
:
if
not
bpy
.
data
.
filepath
:
...
@@ -116,35 +117,35 @@ class EditLinked(bpy.types.Operator):
...
@@ -116,35 +117,35 @@ class EditLinked(bpy.types.Operator):
try
:
try
:
subprocess
.
Popen
([
bpy
.
app
.
binary_path
,
settings
[
"
linked_file
"
]])
subprocess
.
Popen
([
bpy
.
app
.
binary_path
,
settings
[
"
linked_file
"
]])
except
:
except
:
print
(
"
Error on the new Blender instance
"
)
logger
.
error
(
"
Error on the new Blender instance
"
)
import
traceback
import
traceback
traceback
.
print_exc
()
logger
.
error
(
traceback
.
print_exc
()
)
else
:
else
:
bpy
.
ops
.
wm
.
open_mainfile
(
filepath
=
settings
[
"
linked_file
"
])
bpy
.
ops
.
wm
.
open_mainfile
(
filepath
=
settings
[
"
linked_file
"
])
print
(
"
Opened linked file!
"
)
logger
.
info
(
"
Opened linked file!
"
)
else
:
else
:
self
.
report
({
'
WARNING
'
},
target
.
name
+
"
is not linked
"
)
self
.
report
({
'
WARNING
'
},
target
.
name
+
"
is not linked
"
)
pr
in
t
(
target
.
name
+
"
is not linked
"
)
logger
.
warn
in
g
(
target
.
name
+
"
is not linked
"
)
return
{
'
FINISHED
'
}
return
{
'
FINISHED
'
}
class
ReturnToOriginal
(
bpy
.
types
.
Operator
):
class
WM_OT_
ReturnToOriginal
(
bpy
.
types
.
Operator
):
"""
Load the original file
"""
"""
Load the original file
"""
bl_idname
=
"
wm.return_to_original
"
bl_idname
=
"
wm.return_to_original
"
bl_label
=
"
Return to Original File
"
bl_label
=
"
Return to Original File
"
use_autosave
=
bpy
.
props
.
BoolProperty
(
use_autosave
:
bpy
.
props
.
BoolProperty
(
name
=
"
Autosave
"
,
name
=
"
Autosave
"
,
description
=
"
Save the current file before opening original file
"
,
description
=
"
Save the current file before opening original file
"
,
default
=
True
)
default
=
True
)
@classmethod
@classmethod
def
poll
(
cls
,
context
):
def
poll
(
cls
,
context
:
bpy
.
context
):
return
(
settings
[
"
original_file
"
]
!=
""
)
return
(
settings
[
"
original_file
"
]
!=
""
)
def
execute
(
self
,
context
):
def
execute
(
self
,
context
:
bpy
.
context
):
if
self
.
use_autosave
:
if
self
.
use_autosave
:
bpy
.
ops
.
wm
.
save_mainfile
()
bpy
.
ops
.
wm
.
save_mainfile
()
...
@@ -152,25 +153,29 @@ class ReturnToOriginal(bpy.types.Operator):
...
@@ -152,25 +153,29 @@ class ReturnToOriginal(bpy.types.Operator):
settings
[
"
original_file
"
]
=
""
settings
[
"
original_file
"
]
=
""
settings
[
"
linked_objects
"
]
=
[]
settings
[
"
linked_objects
"
]
=
[]
print
(
"
Back to the original!
"
)
logger
.
info
(
"
Back to the original!
"
)
return
{
'
FINISHED
'
}
return
{
'
FINISHED
'
}
# UI
class
VIEW3D_PT_PanelLinkedEdit
(
bpy
.
types
.
Panel
):
# TODO:Add operators to the File menu?
# Hide the entire panel for non-linked objects?
class
PanelLinkedEdit
(
bpy
.
types
.
Panel
):
bl_label
=
"
Edit Linked Library
"
bl_label
=
"
Edit Linked Library
"
bl_space_type
=
"
VIEW_3D
"
bl_space_type
=
"
VIEW_3D
"
bl_region_type
=
"
TOOLS
"
bl_region_type
=
'
UI
'
bl_category
=
"
Relations
"
bl_category
=
"
View
"
bl_context
=
"
objectmode
"
bl_context
=
'
objectmode
'
@classmethod
@classmethod
def
poll
(
cls
,
context
):
def
poll
(
cls
,
context
:
bpy
.
context
):
return
(
context
.
active_object
is
not
None
)
or
(
settings
[
"
original_file
"
]
!=
""
)
return
(
context
.
active_object
is
not
None
)
or
(
settings
[
"
original_file
"
]
!=
""
)
def
draw
(
self
,
context
):
def
draw_common
(
self
,
scene
,
layout
,
props
):
props
.
use_autosave
=
scene
.
use_autosave
props
.
use_instance
=
scene
.
use_instance
layout
.
prop
(
scene
,
"
use_autosave
"
)
layout
.
prop
(
scene
,
"
use_instance
"
)
def
draw
(
self
,
context
:
bpy
.
context
):
layout
=
self
.
layout
layout
=
self
.
layout
scene
=
context
.
scene
scene
=
context
.
scene
icon
=
"
OUTLINER_DATA_
"
+
context
.
active_object
.
type
icon
=
"
OUTLINER_DATA_
"
+
context
.
active_object
.
type
...
@@ -184,7 +189,7 @@ class PanelLinkedEdit(bpy.types.Panel):
...
@@ -184,7 +189,7 @@ class PanelLinkedEdit(bpy.types.Panel):
if
settings
[
"
original_file
"
]
==
""
and
(
if
settings
[
"
original_file
"
]
==
""
and
(
(
target
and
(
target
and
target
.
library
is
not
None
)
or
target
.
library
is
not
None
)
or
context
.
active_object
.
library
is
not
None
):
context
.
active_object
.
library
is
not
None
):
if
(
target
is
not
None
):
if
(
target
is
not
None
):
...
@@ -193,18 +198,15 @@ class PanelLinkedEdit(bpy.types.Panel):
...
@@ -193,18 +198,15 @@ class PanelLinkedEdit(bpy.types.Panel):
else
:
else
:
props
=
layout
.
operator
(
"
object.edit_linked
"
,
icon
=
"
LINK_BLEND
"
,
props
=
layout
.
operator
(
"
object.edit_linked
"
,
icon
=
"
LINK_BLEND
"
,
text
=
"
Edit Library: %s
"
%
context
.
active_object
.
name
)
text
=
"
Edit Library: %s
"
%
context
.
active_object
.
name
)
props
.
use_autosave
=
scene
.
use_autosave
props
.
use_instance
=
scene
.
use_instance
layout
.
prop
(
scene
,
"
use_autosave
"
)
self
.
draw_common
(
scene
,
layout
,
props
)
layout
.
prop
(
scene
,
"
use_instance
"
)
if
(
target
is
not
None
):
if
(
target
is
not
None
):
layout
.
label
(
text
=
"
Path: %s
"
%
layout
.
label
(
text
=
"
Path: %s
"
%
target
.
library
.
filepath
)
target
.
library
.
filepath
)
else
:
else
:
layout
.
label
(
text
=
"
Path: %s
"
%
layout
.
label
(
text
=
"
Path: %s
"
%
context
.
active_object
.
library
.
filepath
)
context
.
active_object
.
library
.
filepath
)
elif
settings
[
"
original_file
"
]
!=
""
:
elif
settings
[
"
original_file
"
]
!=
""
:
...
@@ -215,19 +217,17 @@ class PanelLinkedEdit(bpy.types.Panel):
...
@@ -215,19 +217,17 @@ class PanelLinkedEdit(bpy.types.Panel):
layout
.
separator
()
layout
.
separator
()
#XXX - This is for nested linked assets... but it only works
#
XXX - This is for nested linked assets... but it only works
#
when launching a new Blender instance. Nested links don't
# when launching a new Blender instance. Nested links don't
#
currently work when using a single instance of Blender.
# currently work when using a single instance of Blender.
props
=
layout
.
operator
(
"
object.edit_linked
"
,
props
=
layout
.
operator
(
"
object.edit_linked
"
,
text
=
"
Edit Library: %s
"
%
context
.
active_object
.
instance_collection
.
name
,
text
=
"
Edit Library: %s
"
%
context
.
active_object
.
instance_collection
.
name
,
icon
=
"
LINK_BLEND
"
)
icon
=
"
LINK_BLEND
"
)
props
.
use_autosave
=
scene
.
use_autosave
props
.
use_instance
=
scene
.
use_instance
self
.
draw_common
(
scene
,
layout
,
props
)
layout
.
prop
(
scene
,
"
use_autosave
"
)
layout
.
prop
(
scene
,
"
use_instance
"
)
layout
.
label
(
text
=
"
Path: %s
"
%
layout
.
label
(
text
=
"
Path: %s
"
%
context
.
active_object
.
instance_collection
.
library
.
filepath
)
context
.
active_object
.
instance_collection
.
library
.
filepath
)
else
:
else
:
props
=
layout
.
operator
(
"
wm.return_to_original
"
,
icon
=
"
LOOP_BACK
"
)
props
=
layout
.
operator
(
"
wm.return_to_original
"
,
icon
=
"
LOOP_BACK
"
)
...
@@ -237,31 +237,50 @@ class PanelLinkedEdit(bpy.types.Panel):
...
@@ -237,31 +237,50 @@ class PanelLinkedEdit(bpy.types.Panel):
else
:
else
:
layout
.
label
(
text
=
"
%s is not linked
"
%
context
.
active_object
.
name
,
layout
.
label
(
text
=
"
%s is not linked
"
%
context
.
active_object
.
name
,
icon
=
icon
)
icon
=
icon
)
class
TOPBAR_MT_edit_linked_submenu
(
bpy
.
types
.
Menu
):
bl_label
=
'
Edit Linked Library
'
bl_idname
=
'
view3d.TOPBAR_MT_edit_linked_submenu
'
def
draw
(
self
,
context
):
self
.
layout
.
separator
()
self
.
layout
.
operator
(
OBJECT_OT_EditLinked
.
bl_idname
)
self
.
layout
.
operator
(
WM_OT_ReturnToOriginal
.
bl_idname
)
addon_keymaps
=
[]
addon_keymaps
=
[]
classes
=
(
OBJECT_OT_EditLinked
,
WM_OT_ReturnToOriginal
,
VIEW3D_PT_PanelLinkedEdit
,
TOPBAR_MT_edit_linked_submenu
)
def
register
():
def
register
():
bpy
.
app
.
handlers
.
load_post
.
append
(
linked_file_check
)
bpy
.
app
.
handlers
.
load_post
.
append
(
linked_file_check
)
bpy
.
utils
.
register_class
(
EditLinked
)
bpy
.
utils
.
register_class
(
ReturnToOriginal
)
for
c
in
classes
:
bpy
.
utils
.
register_class
(
PanelLinkedEdit
)
bpy
.
utils
.
register_class
(
c
)
# Is there a better place to store this properties?
bpy
.
types
.
Scene
.
use_autosave
=
bpy
.
props
.
BoolProperty
(
bpy
.
types
.
Scene
.
use_autosave
=
bpy
.
props
.
BoolProperty
(
name
=
"
Autosave
"
,
name
=
"
Autosave
"
,
description
=
"
Save the current file before opening a linked file
"
,
description
=
"
Save the current file before opening a linked file
"
,
default
=
True
)
default
=
True
)
bpy
.
types
.
Scene
.
use_instance
=
bpy
.
props
.
BoolProperty
(
bpy
.
types
.
Scene
.
use_instance
=
bpy
.
props
.
BoolProperty
(
name
=
"
New Blender Instance
"
,
name
=
"
New Blender Instance
"
,
description
=
"
Open in a new Blender instance
"
,
description
=
"
Open in a new Blender instance
"
,
default
=
False
)
default
=
False
)
# add the function to the file menu
bpy
.
types
.
TOPBAR_MT_file_external_data
.
append
(
TOPBAR_MT_edit_linked_submenu
.
draw
)
# Keymapping (deactivated by default; activated when a library object is selected)
# Keymapping (deactivated by default; activated when a library object is selected)
kc
=
bpy
.
context
.
window_manager
.
keyconfigs
.
addon
kc
=
bpy
.
context
.
window_manager
.
keyconfigs
.
addon
if
kc
:
# don't register keymaps from command line
if
kc
:
# don't register keymaps from command line
km
=
kc
.
keymaps
.
new
(
name
=
"
3D View
"
,
space_type
=
'
VIEW_3D
'
)
km
=
kc
.
keymaps
.
new
(
name
=
"
3D View
"
,
space_type
=
'
VIEW_3D
'
)
kmi
=
km
.
keymap_items
.
new
(
"
object.edit_linked
"
,
'
NUMPAD_SLASH
'
,
'
PRESS
'
,
shift
=
True
)
kmi
=
km
.
keymap_items
.
new
(
"
object.edit_linked
"
,
'
NUMPAD_SLASH
'
,
'
PRESS
'
,
shift
=
True
)
kmi
.
active
=
True
kmi
.
active
=
True
...
@@ -272,10 +291,9 @@ def register():
...
@@ -272,10 +291,9 @@ def register():
def
unregister
():
def
unregister
():
bpy
.
utils
.
unregister_class
(
EditLinked
)
bpy
.
utils
.
unregister_class
(
ReturnToOriginal
)
bpy
.
app
.
handlers
.
load_post
.
remove
(
linked_file_check
)
bpy
.
utils
.
unregister_class
(
PanelLinkedEdit
)
bpy
.
types
.
TOPBAR_MT_file_external_data
.
remove
(
TOPBAR_MT_edit_linked_submenu
)
bpy
.
app
.
handlers
.
load_post
.
remove
(
linked_file_check
)
del
bpy
.
types
.
Scene
.
use_autosave
del
bpy
.
types
.
Scene
.
use_autosave
del
bpy
.
types
.
Scene
.
use_instance
del
bpy
.
types
.
Scene
.
use_instance
...
@@ -285,6 +303,9 @@ def unregister():
...
@@ -285,6 +303,9 @@ def unregister():
km
.
keymap_items
.
remove
(
kmi
)
km
.
keymap_items
.
remove
(
kmi
)
addon_keymaps
.
clear
()
addon_keymaps
.
clear
()
for
c
in
reversed
(
classes
):
bpy
.
utils
.
unregister_class
(
c
)
if
__name__
==
"
__main__
"
:
if
__name__
==
"
__main__
"
:
register
()
register
()
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment