Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create "constructor" constraints. #272

Merged
merged 11 commits into from
Sep 20, 2022
Merged

Create "constructor" constraints. #272

merged 11 commits into from
Sep 20, 2022

Conversation

amrsoll
Copy link
Collaborator

@amrsoll amrsoll commented Aug 24, 2022

Fixes #258

20220914_12h50m35s_grim
20220914_12h47m27s_grim

TODO

  • Update constraint value from the attached entity instead of the solver .. hmmm
  • Change look
  • Make dimension read only when is_reference is True.
  • Possibly create class DimensionalConstraint in base_constraint.py
  • Fix bug where color is not proper during mouse hover right after switching reference mode
  • Revert change where reference constraints are filtered out of the constraints menu

@github-actions

This comment was marked as off-topic.

@amrsoll amrsoll changed the title No slvs data when constraint is a contructor. Create "constructor" constraints. Aug 24, 2022
solver.py Outdated Show resolved Hide resolved
@amrsoll amrsoll force-pushed the feat/constraint_constructor branch from 5b618b3 to 3f04da9 Compare August 24, 2022 18:56
@hlorus
Copy link
Owner

hlorus commented Aug 30, 2022

  • Update constraint value from the attached entity instead of the solver .. hmmm

Note: init_props already computes the constraints value and setting from it's entities. Would be great to reuse/split-out that code.

@amrsoll amrsoll mentioned this pull request Sep 3, 2022
model/diameter.py Outdated Show resolved Hide resolved
@hlorus
Copy link
Owner

hlorus commented Sep 6, 2022

Just found out about this:

bpy.ops.wm.properties_edit(
properties_edit()
bpy.ops.wm.properties_edit(data_path="", property_name="", property_type='FLOAT', is_overridable_library=False, description="", use_soft_limits=False, array_length=3, default_int=(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min_int=-10000, max_int=10000, soft_min_int=-10000, soft_max_int=10000, step_int=1, default_float=(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min_float=-10000, max_float=-10000, soft_min_float=-10000, soft_max_float=-10000, precision=3, step_float=0.1, subtype='NONE', default_string="", eval_string="")
Change a custom property's type, or adjust how it is displayed in the interface

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 8, 2022

Well I found out that you cannot make Property values "readonly" for the user on their own, but that you have to declare it in any menu they appear in... or??

Anyway, the functionality is there, I am not super happy with the code structure I went with, I'll have to revise it perhaps..

@hlorus
Copy link
Owner

hlorus commented Sep 8, 2022

Gave it a quick test and it's just awesome when you make a constraint depend on the value of a reference dimension and interactivley drag stuff around!
Is it intentional that reference dimensions don't show up in the constraint browser? IMO that's important to allow adding drivers which will probably be the biggest use-case for this.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 8, 2022

Is it intentional that reference dimensions don't show up in the constraint browser?

Yep, didn't think about the driver situation :) I'll add it back, but I will have to find an other UI trick to make it interact as a "readonly" property

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 8, 2022

For future reference: an old StEx post describes that properties that only have a get function can be seen as greyed out in the UI.

https://blender.stackexchange.com/a/13702

So either I

  • destruct+rebuild the property each time it swaps to/from readonly state, but that breaks drivers and also other code that might have outdated refs to the object
  • edit the Property using the function described earlier, but I still don't get how to find the "path" of the Property to edit.

@hlorus
Copy link
Owner

hlorus commented Sep 8, 2022

For future reference: an old StEx post describes that properties that only have a get function can be seen as greyed out in the UI.

https://blender.stackexchange.com/a/13702

So either I

  • destruct+rebuild the property each time it swaps to/from readonly state, but that breaks drivers and also other code that might have outdated refs to the object
  • edit the Property using the function described earlier, but I still don't get how to find the "path" of the Property to edit.

Shouldn't the layout.enabled flag be the solution here?
https://docs.blender.org/api/current/bpy.types.UILayout.html#bpy.types.UILayout.enabled

Maybe the StEx post is just too old so it wasn't suggested there.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 8, 2022

Shouldn't the layout.enabled flag be the solution here?

The problem is that is disable the whole UILayout in question, column, row... not individual props inside that element.

If the readonly attribute is defined in the Property, it is way more portable and better separation of concerns.

@hlorus
Copy link
Owner

hlorus commented Sep 8, 2022

The problem is that is disable the whole UILayout in question, column, row... not individual props inside that element.

A prop could still be wrapped in it's own sub row..

If the readonly attribute is defined in the Property, it is way more portable and better separation of concerns.

True, also it seems to break the drivers workflow...

I would say a conditional in the setter is the best, least hacky approach.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 11, 2022

A prop could still be wrapped in it's own sub row

I reused the row segments that were available in the menu

conditional in the setter is the best

That cannot be used because We are also updating the value with the entity size. However, because it gets automatically updated, it is not the end of the world if the user is able to input a value because it will get updated if it isn't solver-compatible.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 11, 2022

And I just received the steam deck, so productivity fell through the floor 😂

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 11, 2022

I am looking forward to read your suggestions for improving the code structure :)

@amrsoll amrsoll marked this pull request as ready for review September 11, 2022 12:43
@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 11, 2022

I'm just sad that you cannot create a driver if the UI element is disabled, but it makes sense not to write to that value through the driver. I guess that is potential bug when not having a conditional limiter in the setter function.

@hlorus
Copy link
Owner

hlorus commented Sep 12, 2022

That cannot be used because We are also updating the value with the entity size. However, because it gets automatically updated, it is not the end of the world if the user is able to input a value because it will get updated if it isn't solver-compatible.

We could actually set the property value without triggering the getter/setter/update callbacks, at least from within the constraints classes.

I'm just sad that you cannot create a driver if the UI element is disabled, but it makes sense not to write to that value through the driver. I guess that is potential bug when not having a conditional limiter in the setter function.

IMO it makes sense that it's not possible to add drivers, what's missing is the "copy as new driver" and "driver datapath" options i suppose...

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

I didn't want extra functions to update the private var, but I suppose I can add the extra argument force=False to allow force updating using the same function.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

Also please let me know about cosmetic changes, I re-read that you were thinking of having the value in brackets, maybe we want to dim the color of the font etc...

Copy link
Owner

@hlorus hlorus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few notes so far:

  • It seems like the color changes are breaking the constraint highlight when an operator button is hovered (when its tooltip appears) in the interface. Maybe have a look at the HighlightElement mixin class.
  • Did you try adding a driver so one constraint has the value of a reference constraint? It's quite a bummer that you cannot use "copy as new driver", do you now if there's another simple way for users to add such a driver?
  • Maybe @exegetor could also have a quick look at the checnges regarding the init_props / assign_init_props methods...?

model/base_constraint.py Outdated Show resolved Hide resolved
ui.py Outdated Show resolved Hide resolved
@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

It seems like the color changes are breaking the constraint highlight when an operator button is hovered (when its tooltip appears) in the interface. Maybe have a look at the HighlightElement mixin class.

How so? To me the highlight colors display correctly. What UI item are you hovering when it should highlight? I tried to compare with main without any different behaviour w/regards to highlighting colors.

Did you try adding a driver so one constraint has the value of a reference constraint?

Had to look up how to do that with MakerTales video 👀 but yes! it works only if

  1. You create the driver from constraint A
  2. Make the constraint A reference / readonly
  3. Paste driver into Dimensional constraint B
  4. Experience a bug where the entity is not updated with the constraint as long as the solver doesn't run 😅

I'll make the change with the force=False variable and I'll let you see if that is preferable to making the UI element grayed out.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

Example test file for the feature :)

untitled.blend.zip

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

2 things about re-enabling the UI elements:

  • Even when enabled in the constraint context menu (right click on constraint), the dimension cannot be copied as a driver
  • If re-enabling all constraints in the Constraint UILayout list, then
    • there is no way to differentiate between the reference and normal constraints
    • You can create the driver at anytime from a reference item, no need to switch reference mode :)

On a different note, pasting a driver onto a reference constraint doesn't change the size of the reference measurement. After 2 sec of reflection, that is logical, but will probably confuse users.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 12, 2022

Side note: I created a StEx question for the extra spicy solution: deleting/recreating the setter function

https://blender.stackexchange.com/questions/274411/override-edit-the-get-set-functions-of-a-property

model/base_constraint.py Outdated Show resolved Hide resolved
@hlorus
Copy link
Owner

hlorus commented Sep 13, 2022

It seems like the color changes are breaking the constraint highlight when an operator button is hovered (when its tooltip appears) in the interface. Maybe have a look at the HighlightElement mixin class.

How so? To me the highlight colors display correctly. What UI item are you hovering when it should highlight? I tried to compare with main without any different behaviour w/regards to highlighting colors.

Oops, you are right! The highlight color was just too subtle, sorry about that.

I'll make the change with the force=False variable and I'll let you see if that is preferable to making the UI element grayed out.

IMO we have to go this route, it's too annoying if you cannot create the driver when a constraint is already set to reference. There needs to be some kind of distinction between reference and normal constraints in the sidebar indeed, not sure how exactly tho, maybe just a separate block with a title "Reference:" ?

@hlorus
Copy link
Owner

hlorus commented Sep 13, 2022

2 things about re-enabling the UI elements:

  • Even when enabled in the constraint context menu (right click on constraint), the dimension cannot be copied as a driver
  • If re-enabling all constraints in the Constraint UILayout list, then

Yeah thats a unfortunate limitation, blender doesn't allow to add drivers from popup menus, that's why we need to display the properties in the sidebar....

On a different note, pasting a driver onto a reference constraint doesn't change the size of the reference measurement. After 2 sec of reflection, that is logical, but will probably confuse users.

Yeah ideally the disabled layout would allow to copy as new driver but disallow adding a driver... but i think we found a ok workaround for the moment.

@@ -122,7 +122,7 @@ def _get_msg_entities():
# Store a index-constraint mapping
from collections.abc import Iterable

indices = c.create_slvs_data(self.solvesys, group=group)
indices = c.py_data(self.solvesys, group=group)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's quite the fundamental change here, is it really needed for this PR? I would rather have this in a separate PR and apply it also to entities.

But i'm not actually sure this makes sense, The slvs solve system cannot be created and updated at a later point. So a new one is created everytime the solver runs. If we don't explicitly recreate slvs data py_data might return handles from the last solver run.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to think of a different way to do it so it doesn't have that many changes to the higher level abstractions

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hlorus
Either:

  • I rename the create_slvs_data() in all the constraints and entities that use it.
  • I write the "empty return" return step in all the create_slvs_data() for the dimensional constraints.

The reason I refactored create_slvs_data() to py_data() in the higher level abstraction is because the .py_data attribute is used by the entities to pass on the solver handles.

I can create a separate PR now that refactors all the entities and constraints to

  • have a py_data() function that serves as interface and returns the slvs handles.

    That function should only be implemented by the abstract/mother classes like GenericX

  • have a private function create_slvs_data() that generates the data.

    This function is implemented by all the daughter classes to create handles specific to themselves

I would also suggest a name change for those functions, for example solver_handles() and generate_solver_handles()

@hlorus
Copy link
Owner

hlorus commented Sep 13, 2022

Regarding cosmetics, adding brackets and dimming the text sounds reasonable but i don't have a strong opinion here.

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 13, 2022

blender doesn't allow to add drivers from popup menus

Then I will re-disable the value selection in the popup menu

ideally the disabled layout would allow to copy as new driver but disallow adding a driver...

I haven't tested this, but I believe that a custom Property that only has a get() function and not set() would have that behaviour.

Regarding cosmetics, adding brackets and dimming the text sounds reasonable but i don't have a strong opinion here.

I think we should run a poll in the discord to gauge what people think

@hlorus
Copy link
Owner

hlorus commented Sep 15, 2022

The functionality of init_props is changed here, if i get it right calling assign_init_props would now have the same effects as init_props had before. Yet there are places (operators/base_constraint.py line 69) where init_props is still called. While i haven't tested it i'm afraid this breaks stuff, was it intentional?

@amrsoll
Copy link
Collaborator Author

amrsoll commented Sep 16, 2022

It was intentional, but I feel like I need to open a discussion topic so we don't pollute the PR too much.

@hlorus
Copy link
Owner

hlorus commented Sep 17, 2022

It was intentional, but I feel like I need to open a discussion topic so we don't pollute the PR too much.

Okay then i'd say we can merge this, i haven't found anything braking. Maybe just keep an eye open for reports.

@hlorus hlorus requested review from hlorus and removed request for hlorus September 17, 2022 09:47
@hlorus hlorus merged commit 4caa0fc into main Sep 20, 2022
@vespakoen
Copy link
Collaborator

@amrsoll Looks like this PR broke the Angle constraint ;)

@vespakoen
Copy link
Collaborator

More specifically, this commit: ee09f49

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reference Dimensions
3 participants