Skip to content

Commit b1ea3fc

Browse files
committed
2023.2.0 Update
- Added py-ies-meta-loader, a plugin example of a a custom file format loader - Added an example to create a node material in scripts\05_modules\nodes\modify_node_graph_2023.py - Fixed few issues in the documentation of scripts\04_3d_concepts\modeling\geometry\ files - Fixed few issues in the documentation of scripts\04_3d_concepts\modeling\modeling_commands\* files
1 parent 513723d commit b1ea3fc

22 files changed

+470
-181
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
"""
2+
Copyright: MAXON Computer GmbH
3+
Author: Manuel MAGALHAES
4+
5+
Description:
6+
- Shows how to create a scene loader plugin. This example is the counterpart of the export
7+
plugin. To test it, the exported text file will be needed.
8+
- Shows how to use the description files to present option to the user about how to import the
9+
file. This options will be displayed in a form of a GeDialog to the user, or in the preferences,
10+
in the corresponding Import/Export section. If the function c4d.documents.LoadDocument is used
11+
to load the file, the flag c4d.SCENEFILTER_DIALOGSALLOWED must be defined so that the option will
12+
be presented to the user.
13+
14+
Class/method highlighted:
15+
- c4d.plugins.SceneLoaderData
16+
- SceneLoaderData.Identify()
17+
- SceneLoaderData.Load()
18+
"""
19+
20+
import c4d
21+
22+
# SceneLoader are registered earlier than Cinema 4D Resource parser.
23+
# To have all the constant defined in fies_loader.h, you need to manually parse them
24+
import os
25+
import symbol_parser
26+
symbol_parser.parse_and_export_in_caller(os.path.join(os.path.dirname(__file__), "res"))
27+
28+
PLUGIN_ID = 1059408
29+
30+
31+
class ExampleDialog(c4d.gui.GeDialog):
32+
33+
def CreateLayout(self):
34+
"""
35+
This Method is called automatically when Cinema 4D creates the Layout of the Dialog.
36+
Returns:
37+
bool: False if there was an error, otherwise True.
38+
"""
39+
# Defines the title of the Dialog
40+
self.SetTitle("This is an example Dialog")
41+
42+
# Creates a Ok and Cancel Button
43+
self.AddDlgGroup(c4d.DLG_OK | c4d.DLG_CANCEL)
44+
45+
return True
46+
47+
def Command(self, messageId, bc):
48+
"""
49+
This Method is called automatically when the user clicks on a gadget and/or changes
50+
its value this function will be called. It is also called when a string menu item is selected.
51+
52+
Args:
53+
messageId (int): The ID of the gadget that triggered the event.
54+
bc (c4d.BaseContainer): The original message container.
55+
56+
Returns:
57+
bool: False if there was an error, otherwise True.
58+
"""
59+
# User click on Ok buttonG
60+
if messageId == c4d.DLG_OK:
61+
print("User Click on Ok")
62+
return True
63+
64+
# User click on Cancel button
65+
elif messageId == c4d.DLG_CANCEL:
66+
print("User Click on Cancel")
67+
68+
# Close the Dialog
69+
self.Close()
70+
return True
71+
72+
return True
73+
74+
75+
class IESMetaLoader(c4d.plugins.SceneLoaderData):
76+
"""IESMeta Loader"""
77+
dialog = None
78+
79+
def Init(self, node):
80+
"""
81+
Called when a new instance of this object is created. In this context, this allow to define
82+
the option by default for the SceneLoaderPlugin that will be displayed to the user.
83+
84+
Returns:
85+
bool: False if there was an error, otherwise True.
86+
"""
87+
# Define the default value for the parameters.
88+
self.InitAttr(node, bool, IES_IMPORT_PRINT_TO_CONSOLE)
89+
node[IES_IMPORT_PRINT_TO_CONSOLE] = True
90+
return True
91+
92+
def Identify(self, node, name, probe, size):
93+
"""
94+
Cinema 4D calls this function for every registered scene loader plugin. This function
95+
should return True only if this plugin can handle the file. The parameter 'probe' contain a
96+
small part of the file, usually the 1024 first characters. This allow to check if the header
97+
of the file starts as expected, validating the fact this file can be read by the load
98+
function.
99+
Args:
100+
node (c4d.BaseList2D): The node object.
101+
name (str): The name of the loader.
102+
probe (memoryview): The start of a small chunk of data from the start of the file for
103+
testing this file type. Usually the probe size is 1024 bytes. Never call the buffer
104+
outside this method!
105+
size (int): The size of the chunk for testing this file type.
106+
Returns:
107+
bool: True if the SceneLoaderData can load this kind of files.
108+
"""
109+
# Check if the last three character are equal to 'txt'
110+
if "txt" in name[-3:]:
111+
# Check if the txt file start with the correct header.
112+
if bytes(probe[0:17]).decode().upper() == "IES Meta Exporter".upper():
113+
return True
114+
return False
115+
116+
def Load(self, node, name, doc, filterflags, error, bt):
117+
"""
118+
Called by Cinema 4D to load the file. This method is only called if the identify function
119+
returned True. The parameter 'node' allows to retrieve the options the user defined for this
120+
import.
121+
122+
Args:
123+
node (c4d.BaseList2D): The node object representing the exporter.
124+
name (str): The filename of the file to save.
125+
doc (c4d.documents.BaseDocument): The document that should be saved.
126+
filterflags (SCENEFILTER): Options for the exporter.
127+
error (None): Not supported.
128+
bt (c4d.threading.BaseThread): The calling thread.
129+
130+
Returns:
131+
FILEERROR: Status of the import process.
132+
"""
133+
dialogAllowed = bool(filterflags & c4d.SCENEFILTER_DIALOGSALLOWED)
134+
isMainThread = c4d.threading.GeIsMainThread()
135+
136+
print("is main thread {}".format(isMainThread))
137+
print("is dialog allowed? {}".format(dialogAllowed))
138+
# GUI operation are not allowed if they are not executed from the main thread, always check
139+
# if this is the main thread. Check also if the flag is set to SCENEFILTER_DIALOGSALLOWED to
140+
# sure dialog can be displayed.
141+
if isMainThread:
142+
if dialogAllowed:
143+
# Open a GeDialog
144+
if self.dialog is None:
145+
self.dialog = ExampleDialog()
146+
self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
147+
pluginid=PLUGIN_ID,
148+
defaultw=400,
149+
defaulth=32
150+
)
151+
152+
# Create and display a Popup Menu
153+
menu = c4d.BaseContainer()
154+
menu.InsData(1001, 'Item 1')
155+
menu.InsData(1002, 'Item 2')
156+
menu.InsData(0, '') # Append separator
157+
c4d.gui.ShowPopupDialog(cd=None, bc=menu, x=c4d.MOUSEPOS, y=c4d.MOUSEPOS)
158+
159+
# Display the content of the file if the user check the option in the import options.
160+
# Opens the file in read mode and print all the lines
161+
if node[IES_IMPORT_PRINT_TO_CONSOLE]:
162+
with open(name, "r") as f:
163+
for line in f:
164+
print(line)
165+
return c4d.FILEERROR_NONE
166+
167+
168+
if __name__ == '__main__':
169+
c4d.plugins.RegisterSceneLoaderPlugin(id=PLUGIN_ID,
170+
str="Py-IES Meta (*.txt)",
171+
info=0,
172+
g=IESMetaLoader,
173+
description="fies_loader",
174+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#ifndef _FIES_LOADER_H__
2+
#define _FIES_LOADER_H__
3+
4+
enum
5+
{
6+
7+
fies_loader = 10000,
8+
IES_IMPORT_PRINT_TO_CONSOLE,
9+
IES_IMPORT_GROUP
10+
11+
};
12+
13+
#endif
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CONTAINER fies_loader
2+
{
3+
INCLUDE Fbase;
4+
NAME fies_loader;
5+
6+
GROUP IES_IMPORT_GROUP
7+
{
8+
DEFAULT 1;
9+
10+
BOOL IES_IMPORT_PRINT_TO_CONSOLE {}
11+
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
STRINGTABLE fies_loader
2+
{
3+
fies_loader "IES Import Settings";
4+
IES_IMPORT_GROUP "IES option group";
5+
IES_IMPORT_PRINT_TO_CONSOLE "Print to console?";
6+
7+
8+
}

plugins/readme.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,14 @@ A data class for creating scene saver plugins (custom scene file format exporter
141141

142142
Exporter, exporting all IES Meta information from the current document to a txt files.
143143
Iterates all objects present in the cache of each objects in the scene to retrieve IES light.
144-
144+
145+
## SceneLoaderData
146+
A data class for creating custom scene file format importer.
147+
148+
### py-ies_meta_loader
149+
150+
Importer, creating IES light from a file exported with the ies_meta_exporter.
151+
145152
## BitmapLoaderData
146153
A data class for creating bitmap loader plugins (custom bitmap file format importer).
147154

scripts/03_application_development/gui/dialog/gedialog_modal_r13.py

-3
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
- c4d.gui.GeDialog
1313
- GeDialog.CreateLayout()
1414
- GeDialog.Command()
15-
16-
- Win / Mac
17-
- R13, R14, R15, R16, R17, R18, R19, R20, R21, S22, R23
1815
"""
1916
import c4d
2017

0 commit comments

Comments
 (0)