Note: The following are based on the Blender 2.7x version of the project, other low version may be changed.
When Blender starts to complete, a screen appears, called Splash. The default is open and can be turned off in the settings. In the File menu, click on User Preferences (shortcut key CTRL + ALT + U), in the pop-up window The first tab page, which is the bottom right corner of the interface (Interface), there is an option Show Splash, default tick, close then the next row of Save User Settings. This way, the next time you start the splash will not appear.
Assuming you have downloaded the blender code, the following is the implementation of the C language operator by Splash, and the previous article is about Python's operator.
Datatoc
The folder where the splash resource resides is blender/release/datafiles/, along with various icons, fonts, svg vectors, brushes, and matcap.
Source/blender/editors/datafiles/cmakelists.txt calls the Data_to_c_simple function to convert from a picture format to a C code (in fact, the length plus the binary data), blender Needs to be compiled outside the source code path (out of source build), corresponding to the build in blender-build/release/datafiles/.
Data_to_c_simple (.. /.. /.. /.. /release/datafiles/splash.png SRC)
The Data_to_c_simple function (CMake macro) is defined in the Build_files/cmake/macros.cmake
Data_to_c need to provide File_from, file_to parameters, data_to_c_simple only provide file_from parameters, file_to value is ${file_from}.c.
The command called is datatoc its engineering in source/blender/datatoc/.
The last sentence of the CMakeLists.txt indicates the generation of Bf_editor_datafiles.lib
Blender_add_lib (bf_editor_datafiles "${src}" "${inc}" "${inc_sys}")
Bf_editor_datafiles.vcxproj-Blender-build/lib/debug/bf_editor_datafiles.lib
Blender/source/blenderplayer/cmakelists.txt
Bf_editor_datafiles is included in Blender_sorted_libs, Blender.exe Blenderplayer.exe relies on these engineering libraries.
Target_link_libraries (Blenderplayer ${blender_sorted_libs})
Target_link_libraries (Blender ${blender_sorted_libs})
These image resources are eventually converted into C array data linked to the. exe file.
The advantage is: if the resources are missing (the wrong name, the Chinese characters, or the picture format is wrongly written), the compilation period will be error; If you only replace a picture, the errors can only be found at runtime, resulting in an error.
The downside is that it's not just about replacing the picture resources, it's also a need to recompile. This makes some artists who want to replace splash with their own works.
Main function
The Blender.sln solution contains several projects, and the CMake tool generates additional projects such as All_build/install/package/run_tests/zero_check. Among them, All_build and install equivalent makefile inside the make and install command.
Compile completed, at run time, need to change the startup project from All_build to blender, otherwise it will prompt unable to start program ' Build\x64\debug\all_build ' denied access. (After the right mouse button on the Blender project, select Set as StartUp project)
Everything, start with the main function ...
The main function is source/creator/creator.c in the Blender project, initializing the subsystem (image, modifier, brush, Python, node, material, etc.), processing command line arguments, entering the message loop Wm_main () Or the exit loop runs in the background (the-b parameter can be specified for rendering in the background).
Bli_argsadd (BA, 1, "-B", "--background", "\n\trun in background (often used for ui-less rendering)", Background_mode, NULL );
All applications that have a UI will have a message loop mechanism. Blender is in Wm_main (C);
The implementation of Wm_main in SOURCE/BLENDER/WINDOWMANAGER/INTERN/WM.C, a very simple few lines of code.
voidWm_main (Bcontext *b) { while(1) { /*get events from Ghost, handle window events, add to window queues*/wm_window_process_events (C); /*per window, all events to the window, screens, area and region handlers*/wm_event_do_handlers (C); /*Events has left notes about changes, we handle and cache it*/wm_event_do_notifiers (C); /*Execute cached changes draw*/wm_draw_update (C); }}
In Wm_main (C); The top of the line is about Splash,
if (! g.file_loaded) Wm_init_splash (C);
Blender has two important data structures, Global G; and Userdef U; , see the name of the idea.
The global field file_loaded is of type bool, but the string globally searches for an assignment of 1, which is actually true.
source/blender/windowmanager/intern/wm_operators.c:g.file_loaded = 1;/* prevents splash to show */
File_loaded is true to prevent the loading of splash, otherwise the splash is loaded on startup.
Splash
The code for Splash is in Wm_init_splash (C); This is the line. The
WM is an abbreviation for WindowManager, and C is missing the namespace concept of C + +, which comes with module naming to prevent collisions.
to see where the code is about splash, a very common concept of blender is operator.
Source/blender/windowmanager/intern/wm_init_exit.c
void Wm_init_splash (bcontext *c) { if ((U.uiflag & user_splash_disable) = = 0 ) {WM WindowManager *wm = Ctx_wm_manager (C); Wmwindow *prevwin = Ctx_wm_window (C); if (Wm->windows.first) {Ctx_wm_wi Ndow_set (C, WM ->windows.first); Wm_operator_name_call (C, wm_ot_ Splash , Wm_op_invoke_default, NULL); Ctx_wm_window_set (C, Prevwin); } }}
The bits of u.uiflag were almost exhausted, and the Uiflag2 was opened again. Among them, user_splash_disable corresponds to the above user preferences in the Show SPLASH.
Bcontext is a very important data structure, passed by pointer, function definition in source/blender/blenkernel/intern/context.c, many places reference it, should be defined in the. h file.
Give the variable a good name and make it easier to read the code. Wm_operator_name_call See the name of the operator, according to the name of the call function, such as above is to invoke the "Wm_ot_splash" function.
int Wm_operator_name_call (bcontext *c, Const char *opstring, short Context, Pointerrna *properties) {wmoperatortype *ot = Wm_operatortype_find ( opstring, 0 ); if (OT) { return Wm_operator_name_call_ptr (C, OT, context, properties); return 0 ;}
In BLENDER/SOURCE/BLENDER/WINDOWMANAGER/INTERN/WM_OPERATORS.C you can see various operations on Operator, through functions Wm_operatortype_append You can add new Operator, because there are many operator,blender with their own hash table GHash *global_ops_hash management, Wm_ot_splash is added when the Wm_init () is initialized.
/* called on initialize Wm_init () Span style= "color: #008000;" >*/ void wm_operatortype_init (void /* Reserve size is set based on blender default setup */ Global_ops_hash = BLI_GHASH_STR_NEW_EX ( wm_operatortype_init gh , ) ; ... Wm_operatortype_append (Wm_ot_splash); ...}
The stack of
Calls is such that
int main (int argc, const char **argv)
Wm_init (C, argc, (const char * * *) argv);
Wm_operatortype_init ();
Wm_operatortype_append (Wm_ot_splash); The
Wm_ot_splash,wm is the kind of Operator, _ot_ is the Operator type, which forms part of the Operator ID name, which populates the fields in Wmoperatortype.
Static void Wm_ot_splash (Wmoperatortype *ot) { ot"Splashscreen"; OT"wm_ot_splash"; OT"Open thesplash screen with release info"; OT->invoke = wm_splash_invoke; OT->poll = wm_operator_winactive;}
The previous article talked about name, Idname, description. The struct Wmoperatortype also gives comments. Name is displayed on the UI. Idname name should be the same as the function name, here can be used __FUNC__ macro. Description is a hint message, the mouse on the above will be displayed.
The poll callback function is used to test whether the operator can be executed in the current environment (context). I find that some people do not care about the name of a variable or function when they are reading the code. Poll is the meaning of polling, you can guess the function to be done by name. About function Wm_operator_poll
Invoke is the function call.
Because it is a static function, it is only necessary to search within this file for calls, and other files cannot be called. This is also a search technique.
Static int Const wmevent *unused (event)) { Ui_popup_block_invoke (C, Wm_block_create_splash, NULL); return operator_finished;}
C Returns the status of Operator_finished, corresponding to Python return {"Finished"}.
Then is the Wm_block_create_splash function, draw the splash place, splash above the jump link is also written in this function.
Blender/source/blender/windowmanager/intern/wm_operators.c
StaticUiblock *wm_block_create_splash (Bcontext *c, Aregion *ar,void*UNUSED (ARG)) {... #ifndef with_headlessextern Chardatatoc_splash_png[]; extern intdatatoc_splash_png_size; extern Chardatatoc_splash_2x_png[]; extern intdatatoc_splash_2x_png_size; Imbuf*Ibuf;#elseImbuf*ibuf =NULL;#endif ... }
Splash.png
With_headless name can not understand, CMakeLists.txt explained that is not with the graphical interface of the compilation (Render farm, server-side mode), the default is closed.
Here is a reference to the Splash.png diagram, the project Datatoc used to convert splash.png image resources to the growth datatoc_splash_png_size and binary dump Datatoc_splash_png, as mentioned above.
For the function Wm_operator_invoke, in SOURCE/BLENDER/WINDOWMANAGER/INTERN/WM_EVENT_SYSTEM.C, the call stack is this:
int main (int argc, const char **ARGV)
Wm_main (C);
Wm_init_splash (C);
Wm_operator_name_call (C, "Wm_ot_splash", Wm_op_invoke_default, NULL);
Wm_operator_name_call_ptr (C, OT, context, properties);
Wm_operator_call_internal (C, OT, properties, NULL, context, false);
Wm_operator_invoke (C, OT, event, properties, reports, poll_only);
Static intWm_operator_invoke (Bcontext*c, Wmoperatortype *ot, Wmevent *Event, Pointerrna*properties, Reportlist *reports,Const BOOLpoll_only) { ... if(Op->type->invoke &&Event) {Wm_region_mouse_co (C,Event); if(Op->type->flag &Optype_undo) WM->op_undo_depth++; retval= Op->type->invoke (C, OP,Event); Operator_retval_check (RETVAL); if(Op->type->flag & Optype_undo && ctx_wm_manager (C) = =wm) WM->op_undo_depth--; } Else if(op->type->exec) { if(Op->type->flag &Optype_undo) WM->op_undo_depth++; retval= op->type->exec (C, op); Operator_retval_check (RETVAL); if(Op->type->flag & Optype_undo && ctx_wm_manager (C) = =wm) WM->op_undo_depth--; } Else { /*Debug, important to leave a while, should never happen*/printf ("%s:invalid operator call '%s ' \ n", __func__, ot->idname); } ...}
Wm_operator_invoke
Invoke and Exec are function pointers, and a operator call is illegal if you want to select a fill of two. The splash operator above uses invoke, and their function prototypes are:
Int (*exec) (struct bcontext *, struct wmoperator *);
Int (*invoke) (struct bcontext *, struct wmoperator *, const struct wmevent *);
Invoke has a struct wmevent* parameter that is more than exec, and the return type is int, which is actually the Nameless enum type below.
After calling exec or invoke, the return value will be tested Operator_retval_check (ret).
Invoke is more than Exec's sentence: Wm_region_mouse_co (C, event);
/*operator type return flags:exec (), Invoke () modal (), return values*/enum{Operator_running_modal= (1<<0), operator_cancelled= (1<<1), operator_finished= (1<<2), /*Add this flag if the event should pass through*/Operator_pass_through= (1<<3), /*In case operator got executed outside WM code ... like via Fileselect*/operator_handled= (1<<4), /*used for operators the act indirectly (eg. popup menu) * note:this isn ' t great design (using operators to Trigg ER UI) avoid where possible. */Operator_interface= (1<<5),};#defineOperator_flags_all (\Operator_running_modal|operator_cancelled|operator_finished|Operator_pass_through|operator_handled|Operator_interface| 0)/*Sanity checks for debug mode only*/#defineOperator_retval_check (ret) (void) RET, bli_assert (ret! = 0 && (ret & operator_flags_all) = = ret)
Operator_retval_check
Blender's user preferences can be saved in the. blend file, which is about Splash.
Source/blender/makesrna/intern/rna_userdef.c
Prop = Rna_def_property (Srna, "Show_splash", Prop_boolean, Prop_none);
Rna_def_property_boolean_negative_sdna (prop, NULL, "Uiflag", user_splash_disable);
Rna_def_property_ui_text (prop, "Show Splash", "Display Splash screen on startup");
Source/blender/makesdna/dna_userdef_types.h
user_splash_disable= (1 << 27),
Blender's Splash Code analysis