﻿<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=Dev%3A2.5%2FSource%2FDevelopment%2FWinterCamp%2FTechnicalDesign</id>
	<title>Dev:2.5/Source/Development/WinterCamp/TechnicalDesign - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=Dev%3A2.5%2FSource%2FDevelopment%2FWinterCamp%2FTechnicalDesign"/>
	<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:2.5/Source/Development/WinterCamp/TechnicalDesign&amp;action=history"/>
	<updated>2026-05-14T17:49:19Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=Dev:2.5/Source/Development/WinterCamp/TechnicalDesign&amp;diff=86031&amp;oldid=prev</id>
		<title>Yamyam: 1版 をインポートしました</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:2.5/Source/Development/WinterCamp/TechnicalDesign&amp;diff=86031&amp;oldid=prev"/>
		<updated>2018-06-28T18:40:35Z</updated>

		<summary type="html">&lt;p&gt;1版 をインポートしました&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ja&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← 古い版&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;2018年6月28日 (木) 18:40時点における版&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;ja&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(相違点なし)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Yamyam</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=Dev:2.5/Source/Development/WinterCamp/TechnicalDesign&amp;diff=86030&amp;oldid=prev</id>
		<title>wiki&gt;Terrywallwork: /* Defining RNA */</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=Dev:2.5/Source/Development/WinterCamp/TechnicalDesign&amp;diff=86030&amp;oldid=prev"/>
		<updated>2010-03-30T21:34:50Z</updated>

		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Defining RNA&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== Operator ==&lt;br /&gt;
&lt;br /&gt;
Operators so far work well as tools, but are not as usable for python scripting, or even for nodes if they are ever added (this is not a 2.5 target).  For python it is more useful to specify directly the objects to work on, rather than selecting them or putting them in the context. As a solution, operators should specify which data they work on as properties. A secondary function can then connect values from the context to these operators properties.&lt;br /&gt;
&lt;br /&gt;
====Decoupling Context====&lt;br /&gt;
&lt;br /&gt;
For example the &amp;quot;make parent&amp;quot; operator would specify two RNA properties:&lt;br /&gt;
* objects: RNA collection of Object pointers&lt;br /&gt;
* parent: RNA pointer to an Object&lt;br /&gt;
&lt;br /&gt;
When using the operator as a tool, the context would be mapped like this:&lt;br /&gt;
* selected objects -&amp;gt; objects&lt;br /&gt;
* active object -&amp;gt; parent&lt;br /&gt;
&lt;br /&gt;
In macros the same system would be used, in python however you can directly specify the objects:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
objects = [main.objects[0], main.objects[1]]&lt;br /&gt;
parent = main.objects[2]&lt;br /&gt;
&lt;br /&gt;
make_parent(objects, parent)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionally a more object oriented API could be made, by specifying the property that has the operator as a member function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
object.make_parent(parent)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We'll start with the above method though. Additionally we can support output properties. For adding an object, it would be good to return the new object.  Hence each operator should have a list of inputs and outputs.&lt;br /&gt;
&lt;br /&gt;
====Limits====&lt;br /&gt;
&lt;br /&gt;
In principle we can specify a lot as inputs and outputs, for example the vertex selection to operate on. However, it's OK to still simply pass the mesh and leave such things for the future, since it would require too much work.&lt;br /&gt;
&lt;br /&gt;
Also, some of the context we can assume to be there. This includes the main and scene context probably, unless the operation is explicitly on the scene for example.&lt;br /&gt;
&lt;br /&gt;
====Settings and Preferences====&lt;br /&gt;
&lt;br /&gt;
Many operators also depend on user preferences, space settings or scene settings. For python it may be better to have them all as operator properties, since otherwise what the operator does is not as reliable. This adds a fair amount of properties, but may be necessary.&lt;br /&gt;
&lt;br /&gt;
====Implementation====&lt;br /&gt;
&lt;br /&gt;
The context adaption function should either become another callback, or could be detected in the exec or invoke functions. An extra callback may be OK since it can be shared between many similar operators along with the poll function.&lt;br /&gt;
&lt;br /&gt;
How exactly such RNA collections with pointers are implemented and who owns the memory is still unsure, currently it can still use always use a ListBase like Context does. If we ever add vertex collections as input this would be quite inefficient, so another system would be useful here, for example using custom iterator functions or retrieving a raw pointer.&lt;br /&gt;
&lt;br /&gt;
== Python Registration  ==&lt;br /&gt;
&lt;br /&gt;
Blender 2.4x uses a script header to register menues however this wont expand well to fit the number of uses Blender 2.5 has for registering... &lt;br /&gt;
&lt;br /&gt;
*Importers &lt;br /&gt;
*Exporters &lt;br /&gt;
*Operators &lt;br /&gt;
*Python Spaces &lt;br /&gt;
*Python UI (buttons window panels, tool UI's) &lt;br /&gt;
*Python Operators &lt;br /&gt;
*Keybindings&lt;br /&gt;
&lt;br /&gt;
Here is how we have agreed python can register the above items in Blender &lt;br /&gt;
&lt;br /&gt;
Instead of parsing headers, scripts are imported which intern runs registration functions (for the above types) which run from the global name space. &lt;br /&gt;
&lt;br /&gt;
UI/Operator scripts should be possible to easily be redistributed and installed.&lt;br /&gt;
&lt;br /&gt;
=== Script Cache  ===&lt;br /&gt;
&lt;br /&gt;
Caching isn't needed immediately but should eventually be added to avoid running too many scripts on start-up. &lt;br /&gt;
&lt;br /&gt;
Importing up to 100's of modules can be slow, this can be improved by only doing this for the first run. Blender can then write a cache file that includes... &lt;br /&gt;
&lt;br /&gt;
**Script name and mtime &lt;br /&gt;
**Defined Keymaps/Operators/Importers etc... see above list. &lt;br /&gt;
*The cache can be used to know which script to import when any of the registrable types are called.&amp;lt;br&amp;gt;So an operator from the cache can be registered but not have its Python function slots filled in until its first called, where it will import the module and fill in the python pointer functions.&lt;br /&gt;
&lt;br /&gt;
== UI Integration  ==&lt;br /&gt;
&lt;br /&gt;
UI ''Regions'' (menu, panel, editor, area) registers their identifier on startup. Identifiers are unique path-like strings such as &amp;quot;View3D/Menu/Mesh&amp;quot;, &amp;quot;Header/Image&amp;quot; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
UI_Register_Region(&amp;quot;identifier&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other code (python, plugins, ...) can register UI definition callbacks for specific identifiers. The registered functions are used to add buttons/menu entries to their respective regions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
UI_Register_Callback(&amp;quot;identifier&amp;quot;, function);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
During drawing phase, UI functions call their respective callbacks so Python can add items in menus, panels in areas, ... &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// UI code for &amp;quot;identifier&amp;quot; section&lt;br /&gt;
&lt;br /&gt;
UI_Execute_Callbacks(&amp;quot;identifier&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;br&amp;gt; Special *subregion* can be defined for UI regions that are repeated many time (think per-bone UI buttons) in which case that &amp;quot;item&amp;quot; is passed in the context (and predefined by the call. &amp;quot;current_bone&amp;quot; or whatnot).&lt;br /&gt;
&lt;br /&gt;
== Python API ==&lt;br /&gt;
&lt;br /&gt;
==== Operator Prototype Code  ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class OBJECT_OT_make_parent(Operator):&lt;br /&gt;
	name = &amp;quot;Make Parent&amp;quot;&lt;br /&gt;
	objects = CollectionProperty(name=&amp;quot;Objects&amp;quot;, type=Object)&lt;br /&gt;
	parent = PointerProperty(name=&amp;quot;Parent&amp;quot;, type=Object)&lt;br /&gt;
&lt;br /&gt;
	def poll(self, context):&lt;br /&gt;
		if len(context.selected_objects) &amp;amp;lt; 1:&lt;br /&gt;
			return report_warning(&amp;quot;No Selected Objects&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
		if not context.active_object:&lt;br /&gt;
			return report_warning(&amp;quot;No Active Object&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
		return True&lt;br /&gt;
	&lt;br /&gt;
	def user(self, context):&lt;br /&gt;
		self.objects = context.selected_objects&lt;br /&gt;
		self.parent = context.active_object&lt;br /&gt;
	&lt;br /&gt;
	def exec(self, context):&lt;br /&gt;
		for ob in self.objects:&lt;br /&gt;
			ob.parent = self.parent&lt;br /&gt;
&lt;br /&gt;
		return Operator.FINISHED&lt;br /&gt;
&lt;br /&gt;
WM.operator_append(OBJECT_OT_make_parent)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above is relatively long, but is required for generating UI, documentation, calling both as a tool and python function, etc. For a quick operator it would still be possible to write it in compact way: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class OBJECT_OT_make_parent(Operator):&lt;br /&gt;
	def exec(self, context):&lt;br /&gt;
		for ob in context.selected_objects:&lt;br /&gt;
			ob.parent = context.active_object&lt;br /&gt;
&lt;br /&gt;
		return Operator.FINISHED&lt;br /&gt;
&lt;br /&gt;
WM.operator_append(OBJECT_OT_make_parent)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
==== Operator Example Code  ====&lt;br /&gt;
&lt;br /&gt;
This example runs svn, however there are some differences with the prototype above. &lt;br /&gt;
&lt;br /&gt;
*rather then having arbitrarily named props in the class define props, use a list that always has the same name. This also gives properties an order. &lt;br /&gt;
*Operator is not in the global namespace currently use bpy.types.Operator&lt;br /&gt;
&lt;br /&gt;
Todo &lt;br /&gt;
&lt;br /&gt;
*returning 'FINISHED' should be replaced with Operator.FINISHED &lt;br /&gt;
*context needs to be wrapped (with rna?) &lt;br /&gt;
*Only float, int and bool properties can be added so far. &lt;br /&gt;
*user() function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt; &lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class SCRIPT_OT_MyOperator(bpy.types.Operator):&lt;br /&gt;
	'''&lt;br /&gt;
	Operator documentatuon text, will be used for the operator tooltip and python docs.&lt;br /&gt;
	'''&lt;br /&gt;
	__idname__ = 'script.myoperator'&lt;br /&gt;
	__label__ = 'My Operator'&lt;br /&gt;
	&lt;br /&gt;
	# List of operator properties, the attributes will be assigned&lt;br /&gt;
	# to the class instance from the operator settings before calling.&lt;br /&gt;
	__props__ = [&lt;br /&gt;
	 FloatProperty(attr=&amp;quot;setting_1&amp;quot;, name=&amp;quot;Example 1&amp;quot;, default=10.0, min=0, max=10, description=&amp;quot;Add info here&amp;quot;),&lt;br /&gt;
	 IntProperty(attr=&amp;quot;setting_2&amp;quot;, default=2),&lt;br /&gt;
	 BoolProperty(attr=&amp;quot;toggle&amp;quot;, default=True)&lt;br /&gt;
	]&lt;br /&gt;
	&lt;br /&gt;
	def execute(self, context):&lt;br /&gt;
		print(&amp;quot;MyOperator.exec - props&amp;quot;)&lt;br /&gt;
		print(self.setting_1)&lt;br /&gt;
		print(self.setting_2)&lt;br /&gt;
		print(self.toggle)&lt;br /&gt;
		return('FINISHED',)&lt;br /&gt;
	&lt;br /&gt;
	def invoke(self, context, event):&lt;br /&gt;
		print(&amp;quot;Invoke&amp;quot;)&lt;br /&gt;
		print(event)&lt;br /&gt;
		return('FINISHED',)&lt;br /&gt;
	&lt;br /&gt;
	def poll(self, context): # poll isnt working yet&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
# add the python class as an operator&lt;br /&gt;
bpy.ops.add(SCRIPT_OT_MyOperator)&lt;br /&gt;
&lt;br /&gt;
# run the operator from python (just like a C operator)&lt;br /&gt;
bpy.ops.script.myoperator(setting_1=0.5,setting_2=100,toggle=False)&lt;br /&gt;
&lt;br /&gt;
# remove the operator (not needed, just to show you can)&lt;br /&gt;
bpy.ops.remove('script.myoperator')&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Defining RNA  ====&lt;br /&gt;
&lt;br /&gt;
It should also be possible to define RNA properties from python, to modify Blender types. The easiest way to do it would be directly on the type, if python allows it. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
Object.shading_rate = FloatProperty(name=&amp;quot;Shading Rate&amp;quot;, range=(0.01, 100.0))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Further it would also be useful to subclass Blender types eventually, for example: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class LuxMaterial(Material):&lt;br /&gt;
	name = &amp;quot;LuxRender Material&amp;quot;&lt;br /&gt;
	brdf = EnumProperty(name=&amp;quot;BRDF&amp;quot;, items=(&amp;quot;Phong&amp;quot;, &amp;quot;Lambert&amp;quot;))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
These would then look just like native Blender properties and types from the outside, allowing UI and documentation to be generated, or used in other scripts again.&lt;br /&gt;
&lt;br /&gt;
==== UI Example  ====&lt;br /&gt;
Work in progress prototype - subtype blender types to define UI panels and menus&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class my_custom_panel(bpyui.PanelType): # this name is used by python as a reference&lt;br /&gt;
	name = &amp;quot;Some Panel&amp;quot; # display name. we may not need this?&lt;br /&gt;
	def draw(self, context):&lt;br /&gt;
		ob = context.scene.object.active&lt;br /&gt;
		&lt;br /&gt;
		# context push/pop?&lt;br /&gt;
		&lt;br /&gt;
		row = []&lt;br /&gt;
		row.append(ob.draw_type)&lt;br /&gt;
		row.append((ob.draw_size, 'SLIDER'))	&lt;br /&gt;
		self.addRow(row)&lt;br /&gt;
		&lt;br /&gt;
		# 'SLIDER' -&amp;gt; bpyui.SLIDER; how to override button name, icon, description, need dictionary to avoid ambiguity?&lt;br /&gt;
		# could do both&lt;br /&gt;
		# OK, by allowing both dictionaries and lists?&lt;br /&gt;
		&lt;br /&gt;
		col = []&lt;br /&gt;
		col.append((bpyop.meshes.transform, {&amp;quot;mode&amp;quot;:'rotation'}, bpyop.INVOKE))&lt;br /&gt;
		col.append((bpyop.meshes.remove_doubles, {&amp;quot;tolerance&amp;quot;:0.0001},  bpyop.EXEC))&lt;br /&gt;
		if ob.type == 'Empty':&lt;br /&gt;
			col.append(ob.empty_draw_type)&lt;br /&gt;
		else:&lt;br /&gt;
			col.append(ob.my_generic_property)&lt;br /&gt;
		&lt;br /&gt;
		self.addColumn(col, 3)&lt;br /&gt;
&lt;br /&gt;
	&lt;br /&gt;
	def poll(self, context):&lt;br /&gt;
		if not context.scene.object.active:&lt;br /&gt;
			return False&lt;br /&gt;
		return True&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
bpyui.registerUI(my_custom_panel, &amp;quot;spaces.buttons.object&amp;quot;)&lt;br /&gt;
# use actual types instead of string? . BUT how will blender reference this internally?&lt;br /&gt;
# maybe...&lt;br /&gt;
# bpyui.spaces.buttons.object.register(my_custom_panel) # irritating PyObject creation for each lookup,&lt;br /&gt;
# &lt;br /&gt;
# alternately registration could be automatic just by subclassing however explicit &lt;br /&gt;
&lt;br /&gt;
# how is this different from defining RNA properties on pytypes?&lt;br /&gt;
# - I guess, just need to see some examples&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class VIEW3D_MT_extras(bpyui.Menu): # do we need this name convention??? is it a uniquer name/id? brecht: it should be unique, don't really care about name convention as long as it is consistent with operators, etc, but think this one is fine&lt;br /&gt;
	name = &amp;quot;Menu Name&amp;quot; # display in the UI&lt;br /&gt;
	&lt;br /&gt;
	def draw(self, context):&lt;br /&gt;
		ob = context.scene.object.active&lt;br /&gt;
		&lt;br /&gt;
		menu = []&lt;br /&gt;
		row.append(ob.dupliGroup) # bool menu toggle&lt;br /&gt;
		row.append(bpyop.meshes.remove_doubles)&lt;br /&gt;
		row.append(bpyui.SEPARATOR)&lt;br /&gt;
		row.append((bpyop.meshes.add_mesh, {'tolerance':0.01}, bpyop.EXEC))&lt;br /&gt;
		self.add(menu)&lt;br /&gt;
		&lt;br /&gt;
	def poll(self, context):&lt;br /&gt;
		if not context.scene.object.active:&lt;br /&gt;
			return False&lt;br /&gt;
		return True&lt;br /&gt;
		&lt;br /&gt;
		# return context.scene.object.active != None&lt;br /&gt;
&lt;br /&gt;
bpyiu.registerUI(myMenu, &amp;quot;spaces.view3d.header.extras&amp;quot;) # &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Script]]&lt;/div&gt;</summary>
		<author><name>wiki&gt;Terrywallwork</name></author>
		
	</entry>
</feed>