i have this problem with this addon… the add modular tree window is blocked i cant change setting for the tree
In 2.77 Object.ray_cast() has more than 3 params it returns.
See here
Edit: When line 538 is changed to
(gothit,hit_pos,face_normal,face_index) = obs.ray_cast(pos,end)
which gets rid of the parameter error, value ‘force’ is 0 and does not change while “obstacle avoidance strength” (repel_force in code) is properly updated.
face_normal stays (0,0,1) and dir.dot(face_normal) is always 1
Hope helps.
Thanks, I was using 2.76.
It helps indeed.
Regarding the error experienced by Ace Dragon, if I create 4 objects, and leave the last one selected, and add a modular tree, it sets the smoothing of the last selected object to smooth. If I un-select it before creating the tree, it leaves it as flat shading. The other objects are not changed. (Blender 2.77, version 2 of the modular tree add-on)
One other minor point, all Add Mesh objects are created where the 3D cursor is, except for modular tree, which always creates it at (0,0,0). This is sometimes an inconvenience (just move after creating), but for cases like obstacle avoidance could get tricky, as you would have to move the obstacle (like a stone wall) to the “right” spot, then create the tree, then move both back. If possible, please use the 3D cursor as the origin point.
The update overall is great - love the new features you are adding!
Thank you for the precisions.
I was thinking of using the cursor position to place an additional force, what do you think about it ?
IMO would be better to use a ‘dummy’ (empty or object) as it would give more precision and control, also stays to keep properties for influence and relation to other data/objects.
3D Cursor for tree origin, yes.
Thanks again & again
Great start! I love the (real) branching and the auto-unwrapping! I have complied a list of problems/suggestions for you to look into: I can add more once I test this out further. Of course, I don’t expect you to implement everything I am saying…just throwing out some stuff to try to improve the best tree add-on yet! BTW I noticed a lot of small problems in the code like “i >0” and “faces += [add_tuple(f,n)for f in end_faces]”…I don’t know if you are trying to code in Blender’s text editor or not, but from my experience PyCharm (free and cross-platform) is the best IDE for python (and Blender’s text editor is a waste of time at the moment). If you try it - and pay attention to what it detects and warns you about - you will find your code is much cleaner, easier to read, and in many cases more efficient. I apologize if I come across as pushy at all, I’m just trying to give helpful feedback.
Problems:
- If roots’ iterations is set to 9 or 11 (and maybe other values too…I’m just guessing but maybe it’s all odd #s > 8…octagons ring a bell? maybe?), normals get flipped inside out
Suggestions:
- Progress display in the terminal…VERY USEFUL!
- Presets (that write to a file in a better location than the sapling add-on)
- Potentially move all properties to tool panel where you can change SEVERAL then hit a “Make Tree” button so that the tree doesn’t need to be completely rebuilt for every setting you change (I have done several add-ons with this framework so if you need help setting that up let me know :))
- Rather than an obstacle “name” put an object selector field and have the user select an object (like #2 I can help with syntax and all if you need it)
- Batch tree generation (to generate lots of trees with predefined settings overnight or on vacation etc.)
- Auto saving of .blend BEFORE starting execution (This lets users force quit blender if it’s taking too long…and not lose their work. All external images, external texts, and the .blend itself should be saved. Again feel free to ask me for help on this: I’ve done it before.)
- Add user prefs for toggling on/off panels in UI that a user doesn’t want and for things like auto saving
- Add a random overall scale setting
- Change the icon to something that conveys the magic button better (ie. “WORLD”, “LOGIC”, “MOD_SKIN”, “SNAP_INCREMENT”, or “MOD_PARTICLES”)
- Add a bitbucket or github repo for everyone to push updates to and get your latest commits
Code Critiques:
- Line 441 just inside Create_tree2 on latest build “Make_roots = create_roots” is not needed as far as I can tell (create_roots should be used in the first if statement)
- The latest version of the script prints “blah” to the console hundreds of times when in some unwrapping loop (not only is this a performance “nuance”, but it is also a bit “unprofessional” don’t you think :eyebrowlift: )
Oh, and I almost forgot…an initial test render with (rather barren) leaves. I think I should have done a few more iterations to get more density?
Yes, unprofessional is quite the best word to describe my code
Thanks a lot for the feedback and all your suggestions, they are indeed very helpful. I must confess my lack of knowledge in the UI syntax, and could actually use your help for the implementations of things like presets. As I don’t consider this addon finished, I didn’t cleaned and optimized the code, resulting in some strange lines as you pointed out; this will eventually be fixed
Thanks for PyCharm, I was indeed using the blender text editor, which is a pain.
As for your test render, I think the best way to obtain good results is to use twigs rather than leaves, and leaves are typically smaller than one would imagine
Yet a marvelous tree !
Don’t transform the tree or click anywhere after adding the tree object. Add mesh > Add modular tree > then press F6 to see settings in a floating menu…
I just answered a question on stack exchange with a fairly detailed add-on demo…you can see a prop where it would be registered and a technique for registering each class. Your props in the make_tree Operator class can just be moved to the register function and then registered in scene (like my example on SE). So for example (class names should be camel case according to pep8 guidelines):
from bpy.types import Scene, Operator, Panel
# UI - TODO
class MakeTreePanel(Panel):
# name of the panel...
bl_label = "Modular Tree"
# used to register panel
bl_idname = "3D_VIEW_PT_layout_MakeTree"
# specifies to make panel in 3D View
bl_space_type = 'VIEW_3D'
# it is in the tools not the properties region
bl_region_type = 'TOOLS'
# only show panel when in object mode
bl_context = "objectmode"
# name of the tab for the panel
# (if this is 'Tools' it will be on the first tab)
bl_category = 'Tree'
# the meat of how to draw the panel, this is VERY similar to your pre-existing draw method :)
# it will basically be as easy as changing your self's to scene's
def draw(self, context):
# context is a parameter so we don't need bpy.context.scene to access props
scene = context.scene
layout = self.layout
# create a new column and label it column
col = layout.column()
col.label("Blank Column", icon="COLLAPSEMENU")
# create a button that is linked to the operator
col.operator("scene.add_tree", icon="WORLD")
# create a property field linked to the prop
col.prop(scene, "create_roots")
# OPERATOR
class MakeTree(bpy.types.Operator):
"""Make a tree"""
bl_idname = "scene.add_tree"
bl_label = "Add_modular_tree"
bl_options = {"REGISTER","UNDO"}
def execute(self,context):
seed(self.SeedProp)
# no need for a billion args :)
# to access any prop use at the beginning of a function/method
# scene = bpy.context.scene
# then use,
# scene.prop_name
Create_tree2()
return {'FINISHED'}
classes = [MakeTree, MakeTreePanel]
def register():
# register all classes
for i in classes
bpy.utils.register_class(i)
# register props
Scene.create_roots = BoolProperty(name = "create roots", default = False)
# ... the rest of your props here too
# not needed anymore b/c would be in panel
bpy.types.INFO_MT_mesh_add.append(add_tree_button)
def unregister():
# unregister classes
for i in classes:
bpy.utils.unregister_class(i)
# unregister props
del Scene.create_roots
# ... the rest of your props here too
# not needed anymore b/c would be in panel
bpy.types.INFO_MT_mesh_add.remove(add_tree_button)
if __name__ == "__main__":
register()
So you do have a github repo :eek:? Don’t feel like pushing your local repo? If you can, I think I will be able to make a pull request for some of these ui changes for you…and you can keep working on the fun and awesome stuff! I’m sure others would love to help you as well, as this is something the Blender community has been needing (for free) for quite a while now! After all, you have the ability to merge or not merge whatever we throw at you :eyebrowlift:.
Oh wow, great addon Maxime. Thank you for doing this, and thank you for sharing.
I am trying to use this for a racing track mod, and I was wondering if it is possible to start with anything lower than an octogon. It would have a significant impact on poly count, while not very visible graphic wise (trees would be at some distance from user).
Does this option exists already in the plugin ?(and I don’t find it)
If not, is it possible for me to change something directly in the code maybe ?
Alright, here is a brief rundown on a simple preset system…First off, we need to understand find out where the addon is. This can be easily done by:
import os
# this is where the addon has found itself after registry
addon_filepath = os.path.dirname(__file__)
# go to a folder for your presets
# this essentially does:
# str(addon_filepath) + "/" + "modular_tree_presets"
# but it will work on any os
presets_folder = os.path.join(addon_filepath, "modular_tree_presets")
# make the folder if it doesn't exist
if not os.path.exists(presets_folder):
os.makedirs(presets_folder)
# get a path to an actual preset file
preset = os.path.join(addon_filepath, "demo_preset_name.preset")
# use this to open a file for reading
with open(preset, "r") as p:
preset_text = p.read()
# use this to overwrite preset file (replace the "w" with an "a" to append instead of overwrite)
with open(preset, "w") as p:
print("This is the text to print", file=p, flush=True)
Setup some sort of system for how you will store presets ie.
I would suggest using a two character abbreviation for each prop with the value separated by a comma and the props separated by a semi-colon.
preset_text = "PropA, 1; PropB, 3.5;"
better_preset_text = "pa,2; gt,5;"
To read in the preset, split the string that reading returns by semi-colon to get:
read_in = "pa,2; gt,5;"
props = read_in.split(";")
>>> ["pa,2", "gt,5"]
You can split again by a comma in a for loop if you like, then do a series of if-elif-else checks to assign the read in values to your properties. Of course you’ll need to convert to the right type first, i.e. int(“2”) = 2.
Sorry for my silence, I wasn’t home.
-Luchian: Thank you, non octagon based trees will probably be a thing, but for now I’m targeting optimization and UI changes, as well as the things discussed with Graphics_Dev.
-Graphics_Dev: Thanks a lot for your help ! I must admit that I am not used to github (to be honest, I am not used to many things, as my skills are mostly theoretical ) but it seems quite straight forward, and I’ve just created a repo here.
Thank you again, I sometimes find myself lazy and unwilling to improve the addon, but all your help and feedback sure motivates me !
Take a look at this:
I use this on all my projects, but you’re the owner for this one so its up to you! Would you like to use this branching model? I know it may seem like a lot of stuff I’m throwing at you, and if its too much, I’m sorry.
For now I’ll set this up with a master/develop/feature branch on my local repo and you can accept the pull request if you’d like…I already cloned the repo and will hopefully give you a UI update pull request soon.
For more motivation, I want to say that I already used your tree generator in a recent scene of mine and it in its current state, worked pretty well for that purpose (which I one reason why I want to see this developed further).
I can see tons of Blender users using your generator and dropping sapling should it get to the point of being at parity in terms of possible tree types. The skinning is a major advantage, editing the tree after the fact is trivial, and the root generation is completely unique.
I just made a pull request for an updated UI. Its not perfect, but it should do for now. This addon definitely needs some cleanup to make it fun to work on for you
I am looking forward to seeing what wonders you can do with this!
If you merge my pull request, just remember that from now on, to access a prop, use scene.prop_name, where scene = bpy.context.scene
You may want to consider adding license information like this to the beginning of your script (taken right from blender) to guarantee that the addon will remain free and open source forever and to protect you from warranty issues:
# ##### BEGIN GPL LICENSE BLOCK ######
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
Graphics_Dev
I like the panel a lot, it makes organizing the properties way easier, but how can I update the last created tree without having to delete it and create another ?