mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Draw all the categories tab even if project doesn't exist. Basically, remove poll function that decides this. See PR description for images Pull Request: https://projects.blender.org/blender/blender/pulls/163183
307 lines
9.1 KiB
Python
307 lines
9.1 KiB
Python
# SPDX-FileCopyrightText: 2026 Blender Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import bpy
|
|
from bpy.types import Header, Menu, Panel
|
|
|
|
from bpy.app.translations import (
|
|
pgettext_iface as iface_,
|
|
contexts as i18n_contexts,
|
|
)
|
|
|
|
from .space_userpref import CenterAlignMixIn
|
|
|
|
|
|
MAIN_SECTION_NAME = "General"
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Header
|
|
|
|
class PROJECT_HT_header(Header):
|
|
bl_space_type = 'PROJECT'
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
layout.template_header()
|
|
PROJECT_MT_editor_menus.draw_collapsible(context, layout)
|
|
layout.separator_spacer()
|
|
|
|
|
|
class PROJECT_MT_editor_menus(Menu):
|
|
bl_idname = "PROJECT_MT_editor_menus"
|
|
bl_label = ""
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
layout.menu("PROJECT_MT_view")
|
|
layout.menu("PROJECT_MT_save_load", text="Project", text_ctxt=i18n_contexts.editor_preferences)
|
|
|
|
|
|
class PROJECT_MT_view(Menu):
|
|
bl_label = "View"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
project_space = context.space_data
|
|
|
|
layout.prop(project_space, "show_region_ui")
|
|
|
|
layout.separator()
|
|
|
|
layout.menu("INFO_MT_area")
|
|
|
|
|
|
class PROJECT_MT_save_load(Menu):
|
|
bl_label = "Save & Load"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
prefs = context.preferences
|
|
|
|
layout.prop(prefs, "use_project_auto_save", text="Auto-Save Project")
|
|
layout.operator("project.save_project", text="Save Project")
|
|
|
|
|
|
class PROJECT_MT_add_variable(Menu):
|
|
bl_label = "Add Variable"
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
layout.operator("project.add_variable", text="String", icon='NONE').variable_type = 'STRING'
|
|
layout.operator("project.add_variable", text="Filepath", icon='NONE').variable_type = 'FILEPATH'
|
|
layout.separator()
|
|
layout.operator("project.add_variable", text="Integer", icon='NONE').variable_type = 'INTEGER'
|
|
layout.operator("project.add_variable", text="Float", icon='NONE').variable_type = 'FLOAT'
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Execution Area
|
|
#
|
|
# Shown when header is hidden.
|
|
|
|
class PROJECT_PT_save_project(Panel):
|
|
bl_label = "Save Project"
|
|
bl_space_type = 'PROJECT'
|
|
bl_region_type = 'EXECUTE'
|
|
bl_options = {'HIDE_HEADER'}
|
|
|
|
def draw(self, context):
|
|
layout = self.layout.row()
|
|
layout.operator_context = 'EXEC_AREA'
|
|
|
|
layout.menu("PROJECT_MT_save_load", text="", icon='COLLAPSEMENU')
|
|
|
|
# Save button.
|
|
if not context.preferences.use_project_auto_save and bpy.data.project is not None:
|
|
# Show '*' to let users know the project has been modified.
|
|
# It is shown to the left so that it is visible when the sidebar is narrow,
|
|
# and for consistency with unsaved files in the title bar.
|
|
layout.operator(
|
|
"project.save_project",
|
|
text=("* " if bpy.data.project.is_dirty else "") + iface_("Save Project"),
|
|
icon='FILE_TICK',
|
|
translate=False,
|
|
)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Navigation Bar
|
|
|
|
class PROJECT_PT_navigation_bar(Panel):
|
|
bl_label = "Project Navigation"
|
|
bl_space_type = 'PROJECT'
|
|
bl_region_type = 'UI'
|
|
bl_category = "Navigation"
|
|
bl_options = {'HIDE_HEADER'}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return True
|
|
|
|
def draw(self, context):
|
|
layout = self.layout
|
|
|
|
space_data = context.space_data
|
|
|
|
col = layout.column()
|
|
|
|
if bpy.data.project is None:
|
|
# If there's no project, we need to make sure the UI for creating a
|
|
# new project is visible. That UI is in the main section, so we
|
|
# ensure it's the active section.
|
|
space_data.active_section = MAIN_SECTION_NAME
|
|
col.enabled = False
|
|
|
|
col.scale_x = 1.3
|
|
col.scale_y = 1.3
|
|
col.prop(space_data, "active_section", expand=True)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Main Area
|
|
|
|
class PROJECT_PT_main(Panel, CenterAlignMixIn):
|
|
bl_label = "Project"
|
|
bl_translation_context = i18n_contexts.editor_preferences
|
|
bl_space_type = 'PROJECT'
|
|
bl_region_type = 'WINDOW'
|
|
bl_category = MAIN_SECTION_NAME
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return bpy.data.project is not None
|
|
|
|
def draw_centered(self, context, layout):
|
|
project = bpy.data.project
|
|
|
|
col = layout.column()
|
|
col.prop(project, "name")
|
|
col.prop(project, "root_path")
|
|
|
|
|
|
class PROJECT_PT_main_unset(Panel, CenterAlignMixIn):
|
|
bl_label = "No Project"
|
|
bl_space_type = 'PROJECT'
|
|
bl_region_type = 'WINDOW'
|
|
bl_options = {'HIDE_HEADER'}
|
|
bl_category = MAIN_SECTION_NAME
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
return not PROJECT_PT_main.poll(context)
|
|
|
|
def draw_centered(self, context, layout):
|
|
col = layout.column()
|
|
col.separator(factor=2.0)
|
|
|
|
if context.blend_data.filepath == "":
|
|
row = col.row()
|
|
row.alignment = 'CENTER'
|
|
row.label(
|
|
text="No active project.",
|
|
icon='STATUS_INFO',
|
|
)
|
|
col.separator()
|
|
|
|
row = col.row()
|
|
row.label_multiline(
|
|
text="Save the current file, and make sure to place it in a folder that will be part of the project",
|
|
alignment='CENTER')
|
|
|
|
row = col.row()
|
|
row.label_multiline(
|
|
text="Alternatively, open a file inside of a project directory to see its settings.",
|
|
alignment='CENTER')
|
|
|
|
col.separator()
|
|
row = col.row()
|
|
row.alignment = 'CENTER'
|
|
row.operator("wm.save_as_mainfile", text="Save File...", icon='FILE_TICK')
|
|
row.operator("project.open_blend_in_project", icon='FILE_FOLDER')
|
|
else:
|
|
row = col.row()
|
|
row.alignment = 'CENTER'
|
|
row.label(
|
|
text="No active project.",
|
|
icon='STATUS_INFO',
|
|
)
|
|
col.separator()
|
|
|
|
row = col.row()
|
|
row.label_multiline(
|
|
text="Set up a new project by choosing any parent directory of the current file.",
|
|
alignment='CENTER')
|
|
row = col.row()
|
|
row.label_multiline(
|
|
text="Alternatively, open a file inside of a project directory to see its settings.",
|
|
alignment='CENTER')
|
|
|
|
col.separator()
|
|
row = col.row()
|
|
row.alignment = 'CENTER'
|
|
row.operator("project.new_project", text="New Project...", icon='ADD')
|
|
row.operator("project.open_blend_in_project", icon='FILE_FOLDER')
|
|
|
|
|
|
class PROJECT_UL_variables(bpy.types.UIList):
|
|
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
|
col = layout.column()
|
|
col.prop(item, "name", text="", expand=False, emboss=False)
|
|
|
|
col = layout.column()
|
|
col.alignment = 'RIGHT'
|
|
col.active = False
|
|
match item.type:
|
|
case 'INTEGER':
|
|
col.label(text=str(item.value))
|
|
case 'FLOAT':
|
|
col.label(text="{:.3f}".format(item.value))
|
|
case 'STRING':
|
|
col.label(text=str(item.value))
|
|
|
|
|
|
class PROJECT_PT_variables(Panel):
|
|
bl_label = "Variables"
|
|
bl_space_type = 'PROJECT'
|
|
bl_region_type = 'WINDOW'
|
|
bl_category = "Variables"
|
|
|
|
def draw(self, context):
|
|
project = bpy.data.project
|
|
|
|
layout = self.layout
|
|
|
|
row = layout.row()
|
|
row.template_list(
|
|
listtype_name="PROJECT_UL_variables",
|
|
list_id="Variables",
|
|
dataptr=project,
|
|
propname="variables",
|
|
item_dyntip_propname="description",
|
|
active_dataptr=project,
|
|
active_propname="active_variable_index",
|
|
)
|
|
|
|
col = row.column(align=True)
|
|
col.menu("PROJECT_MT_add_variable", text="", icon='ADD')
|
|
col.operator("project.remove_variable", text="", icon='REMOVE')
|
|
col.separator()
|
|
col.operator("project.move_variable", text="", icon='TRIA_UP').direction = 'UP'
|
|
col.operator("project.move_variable", text="", icon='TRIA_DOWN').direction = 'DOWN'
|
|
|
|
col = layout.column()
|
|
col.use_property_split = True
|
|
col.alignment = 'LEFT'
|
|
col.separator(factor=1)
|
|
|
|
if project.active_variable_index >= 0 and project.active_variable_index < len(project.variables):
|
|
var = project.variables[project.active_variable_index]
|
|
col.prop(var, "type")
|
|
if var.type == 'STRING':
|
|
col.prop(var, "subtype")
|
|
col.prop(var, "name")
|
|
col.prop(var, "value")
|
|
col.prop(var, "description")
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Register
|
|
|
|
classes = (
|
|
PROJECT_HT_header,
|
|
PROJECT_MT_editor_menus,
|
|
PROJECT_MT_view,
|
|
PROJECT_MT_save_load,
|
|
PROJECT_MT_add_variable,
|
|
PROJECT_PT_navigation_bar,
|
|
PROJECT_PT_save_project,
|
|
PROJECT_PT_main_unset,
|
|
PROJECT_PT_main,
|
|
PROJECT_PT_variables,
|
|
PROJECT_UL_variables,
|
|
)
|