Material Slots: Why they're so weird, and how they could be less weird. #112391
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#112391
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Update
I've been informed that a full re-design of this system is actually on the table, and I posted a proposal for that here: #99996 (comment)
Preface
We all know that material slots are wack. In this task I'd like to make sure that these issues are acknowledged and collected.
This is intended as a discussion starter.
I'll present some issues with the current system, try to reverse engineer why it is the way it is, and then I propose a set of fixes to improve things without re-working from the ground up.
Let's go.
Removing Slots: UI
I think an operator to remove all slots from an object is blatantly missing, which makes this the least problematic aspect of the system.
Removing Slots: PyAPI
The only way to remove individual materials in current PyAPI without bpy.ops is
Object.data.materials.pop(index=0)
.However, this call behaves with complete insanity when there are material slots present which are linked to the Object, rather than the Data.
last slot. Even if we passed
index=0
, it will remove the last of many elements, without warnings or error.Adding Slots: UI
Plus Button
Adding a slot via the + button will have that slot linked to whatever the previously active slot was linked to, if there was an active one.
This is not normally done when adding new elements in lists in other areas of Blender.
Also, the default value of the
link
property is'DATA'
, and yet, when adding the first material slot, it gets initialized withlink='OBJECT'
. Based on the knowledge I gained from creating this post, I think material slots should always default tolink='DATA'
.ID Selector Drop-down
Slots created this way always have
link='DATA'
. Why the change of heart, compared to the + button? Well in any case, I prefer this behaviour.Adding Slots: PyAPI
The only way to add a slot via Py is
my_obj.data.materials.append(None)
. This does not return the added slot, and it is alwayslink='DATA'
.Also, from the caller's perspective, this is a bit weird. We're adding an element to some list, because through some callback, that will create an element in another list that we actually care about. Or well, that's because as someone who hasn't done a deep dive into this system, you THINK you care about Material Slots on Objects, when in reality, they are kind of useless. The materials list on the Mesh is what's actually the fundamental data that you care about. With that mindset, the call makes a lot more sense.
Why Material Slots are Weird: They are Overrides from the 90's.
This wasn't clear to me until today, but I finally see the light. Material Slots are just an ultra-primitive, and poorly implemented Override system.
Their purpose is to let you to have a single Mesh, used by multiple Objects, and change the material assignments per Object. And that's it. If we didn't want to have that functionality, we wouldn't need Material Slots stored on Objects, and we would just have a Materials list on Meshes, and that would be perfectly fine.
Anyways, I'm not saying we should get rid of this, it's obviously useful, but for now, let me show you some of the utterly broken behaviours you can achieve with the current system.
Unintentionally un-assigning materials from polygons on another user of the mesh:
Shuffling around the material-to-polygon assignments on another user of the mesh:
It's even possible to get an object with no material slots to have a material:
Proposal to leave the system as is, but just fix it
MaterialSlot.link
property.MaterialSlot.original_material
, which is actually a function that returns the material that the mesh has in this slot.MaterialSlot.override_material
, which is what it says.MaterialSlot.material
becomes read-only, and returns the override_material unless it is None, in which case it returns the original_material, even if it is None. Add-on devs need to change material assignments to use override_material.I believe this set of changes would fix all of the above issues, without re-working the system from scratch.Isn't this
Remove Unused Slots
in the Material Specials menu?Maybe a typo here because index 3 is the 4th material slot which would be the first slot linked to Data in this example. The issue I see here is that removing either index 0, 1, 2 or 3 all remove the slot at index 3 in this case (removing index 4 removes the slot at index 4 as expected).
I made a simple 3.6.2 .blend with
pop(index=0)
script ready to run that demonstrates the issue: MaterialPopBug_3.6.2.blend. The issue appears to be present even back in 2.79 and 2.80.I actually have no idea how you achieved this. As far as I was aware, mesh Objects using the same Mesh would always have the same number of material slots, that being the number of materials on the Mesh (including those which are
None
). If I have multiple mesh Objects using the same Mesh and I add or remove material slots from one of them or from the Mesh directly, all Objects using that mesh update to match the new number of slots (regardless of whether I use the operators or the API functions onMesh.materials
). Similarly, if I change the Mesh of a mesh Object to a different Mesh, the material slots update immediately.It seems there has been some similar discussion around replacing Object-linked materials last year that may be relevant #99996
Thanks a lot for reading through my mad ramblings!
I wasn't aware of this, and tbh it kinda makes all of my efforts here irrelevant. But you know what, now I know everything there is to know about this silly deprecated death row system from a user POV that has confused the hell out of me for the past 7 years, and that brings me great satisfaction.
@HooglyBoogly If there's anything I can do to help #99996 move forward, let me know.
This task can proooobably be closed, but I'll respond to your other points still.
I'm dumb, I thought this was from an add-on that I had installed, LOL. My bad, I removed this from the task now.
You are correct, thank you, I fixed the text and also replaced the video demonstration for more clarity.
I agree this seems to be the intention, but technically all it takes to break it is to spawn a cube and press the + icon.
link='OBJECT'
, the slot will only be created on the active object, and none other. So, the slots fall out of sync as easily as that.So, repro steps look like this:
I think this is the essential part of why object-linked materials don't make sense in Blender. They're not just redundant with overrides though, they're also redundant with modifiers. Modifiers are how we change geometry data per object. The simplicity of that core concept is so powerful, and the fact that object-linked materials don't work like that causes so many problems, many of which you've mentioned here. The simplicity of the core design and data structures is broken.
It would be awesome it you could help with that. Working with you to turn that into an actionable design and get buy-in would be great. Currently I think the best option is to turn it into a modifier (geometry nodes or a builtin modifier). It seems easy to convince developers, but the UX has to be satisfying too, and it needs to work in the important situations object-linked materials do now.
That design task should be improved. It could be much more persuasive and it could give a clearer proposal for what the replacement(s) should look like for each use case.
I posted a proposal in that thread: #99996 (comment)
I'll close this, let's continue there.
I also just realized that the reason my materials were assigned to Object by default is because of a user preference that I guess I must've changed at some point in the past 8 years, lol. Whoops.