Skip to content

Commit

Permalink
Merge pull request #20 from semagnum/v4
Browse files Browse the repository at this point in the history
v1.0.0
  • Loading branch information
semagnum authored Jul 29, 2023
2 parents 8ec0403 + 7e3bec9 commit 398208d
Show file tree
Hide file tree
Showing 30 changed files with 521 additions and 313 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# BLint Quickstart
# Quickstart
See further details in the BLint docs at [semagnum.github.io/blint/](https://semagnum.github.io/blint/).

## Introduction

![BLint preferences window](/doc/img/preferences_window.png)

This addon allows users to run a series of checks on the Blender project
for the purpose of standardization and improving project file conventions.
Automated checks provided by BLint can speed up workflow and
Expand All @@ -18,6 +20,11 @@ In some cases, an issue can be easily fixed.
Each BLint rule has the option of implementing an automatic fix.
External configurations can be used as well as rules that come built-in with BLint.

These rules can be created with the edit rule section, or using the right-click context menu.
Create a rule enforcing a specific property's value in seconds!

![BLint rule creation in the right-click context menu](/doc/img/context_menu.png)

## Installation
1. Go to the main toolbar, select "Edit" and click "Preferences..."
2. Select the "Addons" section
Expand Down
8 changes: 2 additions & 6 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
bl_info = {
'name': 'BLint',
'author': 'Spencer Magnusson',
'version': (0, 3, 1),
'version': (1, 0, 0),
'blender': (2, 93, 0),
'description': 'Custom project linting',
'location': 'Scene',
Expand All @@ -50,11 +50,9 @@
('lint_rule_active', bpy.props.IntProperty(default=0)),
('lint_issue_active', bpy.props.IntProperty(default=0)),
('lint_issues', bpy.props.CollectionProperty(type=model.LintIssue)),
# form creator
('blint_form_rule', bpy.props.PointerProperty(type=model.LintRule)),
('blint_form_issue_active', bpy.props.IntProperty(default=0)),
('blint_form_issues', bpy.props.CollectionProperty(type=model.LintIssue)),
('form_collapsed', bpy.props.BoolProperty(name='Create Rules', default=True))
('form_collapsed', bpy.props.BoolProperty(name='Edit Selected Rule', default=True))
]


Expand All @@ -69,8 +67,6 @@ def register():
for name, prop in properties:
setattr(window_manager, name, prop)

save_load.reload_rules(bpy.context)


def unregister():
panels.unregister()
Expand Down
83 changes: 43 additions & 40 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
{
"rules": [
{
"description": "Default cube exists",
"severity_icon": "INFO",
"category_icon": "MESH_CUBE",
"issue_expr": "'Cube' in bpy.data.objects",
"fix_expr": "bpy.data.objects.remove(bpy.data.objects[\"Cube\"], do_unlink=True)",
"prop_label_expr": ""
},
{
"description": "Avoid numeric name suffixes",
"severity_icon": "INFO",
"category_icon": "OBJECT_DATA",
"issue_expr": "o.name.split('.')[-1].isnumeric()",
"fix_expr": "",
"prop_label_expr": "name",
"iterable_expr": "bpy.data.objects",
"iterable_var": "o"
},
{
"description": "Animated seed is disabled",
"severity_icon": "ERROR",
"category_icon": "TIME",
"prop_label_expr": "name",
"issue_expr": "curr_scene.render.engine == 'CYCLES' and not curr_scene.cycles.use_animated_seed",
"fix_expr": "curr_scene.cycles.use_animated_seed = True",
"iterable_expr": "bpy.data.scenes",
"iterable_var": "curr_scene"
},
{
"description": "Visibility attributes differ",
"severity_icon": "INFO",
"category_icon": "HIDE_OFF",
"prop_label_expr": "name",
"issue_expr": "len({my_object.hide_viewport, my_object.hide_render, my_object.hide_get()}) != 1",
"iterable_expr": "bpy.data.objects",
"iterable_var": "my_object"
}
]
}
"rules": [
{
"description": "Default cube exists",
"enabled": true,
"severity_icon": "INFO",
"category_icon": "MESH_CUBE",
"issue_expr": "'Cube' in bpy.data.objects",
"prop_label_expr": "",
"fix_expr": "bpy.data.objects.remove(bpy.data.objects[\"Cube\"], do_unlink=True)"
},
{
"description": "Avoid numeric name suffixes",
"enabled": true,
"severity_icon": "INFO",
"category_icon": "OBJECT_DATA",
"issue_expr": "o.name.split('.')[-1].isnumeric()",
"prop_label_expr": "o.name",
"iterable_expr": "bpy.data.objects",
"iterable_var": "o"
},
{
"description": "Animated seed is disabled",
"enabled": true,
"severity_icon": "ERROR",
"category_icon": "TIME",
"issue_expr": "curr_scene.render.engine == 'CYCLES' and not curr_scene.cycles.use_animated_seed",
"prop_label_expr": "curr_scene.name",
"fix_expr": "curr_scene.cycles.use_animated_seed = True",
"iterable_expr": "bpy.data.scenes",
"iterable_var": "curr_scene"
},
{
"description": "Visibility attributes differ",
"enabled": true,
"severity_icon": "INFO",
"category_icon": "HIDE_OFF",
"issue_expr": "len({my_object.hide_viewport, my_object.hide_render, my_object.hide_get()}) != 1",
"prop_label_expr": "my_object.name",
"iterable_expr": "bpy.data.objects",
"iterable_var": "my_object"
}
]
}
1 change: 0 additions & 1 deletion config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@


# prevents circular imports between the model and operators, as they reference each other
BT_OT_DELETE_RULE_IDNAME = 'blint.delete_rule'
PACKAGE_NAME = 'blint'
56 changes: 16 additions & 40 deletions doc/create.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,37 @@ Rule Creation
Before you can create your own rules,
you must create a config file to store them
and reference said file in your add-on preferences.
Create an empty text file, with the file extension ".json",
wherever you would like your rules stored.
Create an empty ".json" file wherever you would like your rules stored.

See LintRules in :doc:`model` for more details on rule attributes and settings.

Using the form
------------------------------------
Context Menu
------------

Once you reference the JSON file,
the rule creation form will be available in the preferences.
If you click "Reload rules", you will get an error - that's okay!
There's no rules in it yet, so of course it will fail. Your internal rules should still load.
Every time you create a rule, your JSON config file will be automatically updated and reloaded.
.. image:: img/context_menu.png

Once you have an external config saved,
you can create a new rule by opening the "Create Rules" dropdown and filling out the form.
You can right click on any property in Blender and select the "BLint Create Rule" option.
From there, you can open the add-on preferences
(see Blender Preferences > Add-ons > find "BLint")
and further edit and debug your new rule from there.

Editing the JSON config
--------------------------------------------
Preferences
------------

Here's an example rule config file:
.. image:: img/preferences_window.png

.. code-block:: json
You can edit rules from the preferences window.
Just click the button dropdown "Edit Selected Rule" to view the rule values.

{
"rules": [
{
"description": "Default cube exists",
"severity_icon": "ERROR",
"category_icon": "MESH_CUBE",
"issue_expr": "'Cube' in bpy.data.objects",
"fix_expr": "bpy.data.objects.remove(objs[\"Cube\"], do_unlink=True)",
"prop_label_expr": ""
},
{
"description": "\"Show in front\" set to on",
"severity_icon": "INFO",
"category_icon": "OBJECT_DATA",
"iterable_expr": "bpy.data.objects",
"iterable_var": "obj",
"issue_expr": "obj.show_in_front",
"fix_expr": "obj.show_in_front = False",
"prop_label_expr": "obj.name"
}
]
}
Again, refer to LintRules in :doc:`model` for more details on each field.

Again, refer to LintRules in :doc:`model` for more details.

Rule Creation Tips
----------------------

- Blender can help you find the names of properties! Hover over a given property, right click and select "Copy Data Path" or "Copy Full Data Path". You can use this values in your form. Consider getting the path from Cycle's preview samples property:
- Blender can help you find a property's name! Hover over a given property, right click and select "Copy Data Path" or "Copy Full Data Path". You can use this values in your form. Consider getting the path from Cycle's preview samples property:
- "Copy Full Data Path" results in ``bpy.data.scenes["My Scene"].cycles.preview_samples`` - this is saying: go to my list of scenes, find the one named "My Scene", and access its Cycles preview samples property.
- "Copy Data Path" results in ``cycles.preview_samples`` - notice the lack of scene specification. While this does not say what these attributes belong to, it's briefer and closer to what you need for a rule. Using the above data paths as an example, if your iterable expression is ``bpy.data.scenes`` and your variable name is ``var_scene``, then the reference you can use in an issue expression or fix statement for any given scene is ``var_scene.cycles.preview_samples``.
- Use the `bpy.context <https://docs.blender.org/api/current/bpy.context.html>`_ module to get data relative to the current user state (``bpy.context.scene`` gets the currently visible scene, for example). For data that's project-wide, use the `bpy.data <https://docs.blender.org/api/current/bpy.data.html>`_ module. For the icons, you can find a list of the Blender icons and their names from the built-in Blender addon, "Icon viewer."
- If you want a fix to match a change you have made in a Blend file, you can open Blender's "Info" editor window to see a list of actions you have done as a reference. It is even written like Python code!
- All the fields are checked for ``exec()`` or ``eval()`` to limit potential security vulnerabilities. However, these rules evaluate real Python code, so _be cautious with using others' rules that you're not familiar with.
- All the fields are checked for ``exec()`` or ``eval()`` to limit potential security vulnerabilities. However, these rules evaluate real Python code, so exercise caution when using others' rule configs.
Binary file added doc/img/context_menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/img/preferences_window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 15 additions & 8 deletions doc/model.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
Model classes
=============
Rules and Issues
================

LintIssue
----------

.. automodule:: blint.model.LintIssue
:members:

LintRule
Rule
----------

.. autoclass:: blint.model.LintRule.LintRule
These are definitions of rules or checks against your Blender file.
Any violations will be listed as issues.

.. autoclass:: blint.model.lint_rule.LintRule
:members:

Issue
----------

These are instances of rule violations in your Blender file.

.. automodule:: blint.model.lint_issue
:members:
31 changes: 17 additions & 14 deletions doc/operators.rst
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
BLint operators
=======================

BT\_OT\_CreateRule
BT\_OT\_ContextRule
-----------------------------------------

.. automodule:: blint.operators.BT_OT_CreateRule
.. automodule:: blint.operators.rule_context
:members:

BT\_OT\_DeleteRule
Adding a new Rule
-----------------------------------------

.. automodule:: blint.operators.BT_OT_DeleteRule
.. automodule:: blint.operators.rule_create
:members:

BT\_OT\_FixIssue
Deleting a Selected Rule
-----------------------------------------

.. automodule:: blint.operators.rule_delete
:members:

Fixing an Issue
---------------------------------------

.. automodule:: blint.operators.BT_OT_FixIssue
.. automodule:: blint.operators.issue_fix
:members:

BT\_OT\_ReloadRules
Reloading From and Saving To Disk
------------------------------------------

.. automodule:: blint.operators.BT_OT_ReloadRules
.. automodule:: blint.operators.rule_reload
:members:

BT\_OT\_SelectIcon
Icon Selection
-----------------------------------------

.. automodule:: blint.operators.BT_OT_SelectIcon
.. automodule:: blint.operators.select_icon
:members:

BT\_OT\_SelectIterator
---------------------------------------------

.. automodule:: blint.operators.BT_OT_SelectIterator
.. automodule:: blint.operators.select_iterator
:members:
17 changes: 12 additions & 5 deletions doc/panels.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
BLint Panels and UI Lists
=========================
UI Panels and Lists
===================

Issues Panel
----------------------------------

.. autoclass:: blint.panels.BT_PT_Issues.BT_PT_Issues
This panel is located in your scene properties.
It is also used in the preferences as a debug tool when editing rules.

.. autoclass:: blint.panels.issues_panel.BT_PT_Issues

Issues UI List
----------------------------------

.. autoclass:: blint.panels.BT_UL_Issues.BT_UL_Issues
This lists the individual issues in a scene.

.. autoclass:: blint.panels.issues_list.BT_UL_Issues

Rules UI List
---------------------------------

.. autoclass:: blint.panels.BT_UL_Rules.BT_UL_Rules
This lists the currently used rules in your preferences.

.. autoclass:: blint.panels.rules_list.BT_UL_Rules
2 changes: 1 addition & 1 deletion doc/preferences.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Preferences
-----------

.. autoclass:: blint.preferences.SA_Preferences
.. autoclass:: blint.preferences.preferences.SA_Preferences
:members:
3 changes: 2 additions & 1 deletion model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@
LintRule
]

register, unregister = bpy.utils.register_classes_factory(_registration_order)
if len(bpy.utils.register_classes_factory(_registration_order)) != 0:
register, unregister = bpy.utils.register_classes_factory(_registration_order)
Loading

0 comments on commit 398208d

Please sign in to comment.