-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSketchfab-Exporter.pyp
820 lines (643 loc) · 28.7 KB
/
Sketchfab-Exporter.pyp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
"""
Sketchfab Exporter v1.3.5
Copyright: Erwin Santacruz 2012 (www.990adjustments.com)
Written for CINEMA 4D R13 - R15
Name-US: Sketchfab Exporter v1.3.5
Description-US: Model exporter for Sketchfab.com
Creation Date: 09/06/12
Modified Date: 03/16/13
"""
import c4d
from c4d import documents, gui, plugins, bitmaps, storage
from c4d.threading import C4DThread
import datetime
import os
import json
import urllib2
import shelve
import webbrowser
import zipfile
import threading
# Install and import the poster modules.
try:
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
except ImportError, err:
os_string = "osx"
if c4d.GeGetCurrentOS() == c4d.OPERATINGSYSTEM_WIN:
os_string = "win64"
pythonPath = os.path.join(c4d.storage.GeGetC4DPath(c4d.C4D_PATH_LIBRARY_USER), "python", "packages", os_string)
filePath = os.path.join(os.path.abspath(os.path.dirname(__file__)), "res")
moduleFile = os.path.join(filePath, "poster-0.8.1.zip")
try:
zf = zipfile.ZipFile(moduleFile)
zf.extractall(pythonPath)
zf.close()
except Exception, err:
gui.MessageDialog("Unable to install necessary files. "
"Please check the help for information on manual module installation.", c4d.GEMB_OK)
else:
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
__author__ = "Erwin Santacruz"
__website__ = "http://990adjustments.com"
__sketchfab__ = "http://sketchfab.com"
__twitter__ = "@990adjustments"
__email__ = "[email protected]"
__plugin_title__ = "Sketchfab Exporter"
__version__ = "1.3.5"
__copyright_year__ = datetime.datetime.now().year
__plugin_id__ = 1029390
BTN_ABOUT = 100001
BTN_WEB = 100002
TXT_MODEL_NAME = 100003
EDITXT_MODEL_TITLE = 100004
TXT_DESCRIPTION = 100005
EDITXT_DESCRIPTION = 100006
TXT_TAGS = 100007
EDITXT_TAGS = 100008
TXT_API_TOKEN = 100009
EDITXT_API_TOKEN = 100010
BTN_PUBLISH = 100011
MENU_SAVE_API_TOKEN = 100012
BTN_WEB_990 = 100013
CHK_PRIVATE = 100014
BTN_THUMB_SRC_PATH = 100015
EDITXT_THUMB_SRC_PATH = 100015
EDITXT_PASSWORD = 100016
CHK_ANIMATION = 100017
CHK_PUBLISHDRAFT = 100018
BTN_SKFB_SIGNUP = 100019
BTN_SKFB_TOKEN = 100020
GROUP_WRAPPER = 20000
GROUP_ONE = 20001
GROUP_TWO = 20002
GROUP_THREE = 20003
GROUP_FOUR = 20004
GROUP_FIVE = 20005
GROUP_SIX = 20006
UA_HEADER = 30000
UA_ICON = 30001
# Constants
HELP_TEXT = "Sketchfab Exporter v" + __version__
SETTINGS = "com.990adjustments.SketchfabExport"
SKETCHFAB_URL = "https://api.sketchfab.com/v1/models"
FBX20142 = 1026370
export_options = {c4d.FBXEXPORT_LIGHTS: 1,
c4d.FBXEXPORT_CAMERAS: 0,
c4d.FBXEXPORT_SPLINES: 1,
# Geometry and Materials
c4d.FBXEXPORT_SAVE_NORMALS: 1,
c4d.FBXEXPORT_TEXTURES: 1,
c4d.FBXEXPORT_EMBED_TEXTURES: 1,
c4d.FBXEXPORT_FBX_VERSION: c4d.FBX_EXPORTVERSION_NATIVE,
# cancel all these one
c4d.FBXEXPORT_PLA_TO_VERTEXCACHE: 0,
c4d.FBXEXPORT_SAVE_VERTEX_MAPS_AS_COLORS: 0,
c4d.FBXEXPORT_TRIANGULATE: 0,
c4d.FBXEXPORT_SDS_SUBDIVISION: 1,
c4d.FBXEXPORT_ASCII: 0}
WRITEPATH = os.path.join(storage.GeGetStartupWritePath(), 'Sketchfab')
FILEPATH = os.path.join(WRITEPATH, SETTINGS)
if not os.path.exists(WRITEPATH):
os.mkdir(WRITEPATH)
# Globals
g_uploaded = False
g_error = ""
g_lastUpdated = ""
class Utilities(object):
"""Several helper methods."""
def __init__(self, arg):
super(Utilities, self).__init__()
@staticmethod
def ESOpen_website(site):
"""Opens Website.
:param string site: website url
"""
webbrowser.open(site)
@staticmethod
def ESOpen_about():
"""Show About information dialog box."""
gui.MessageDialog("{0} v{1}\nCopyright (C) {2} {3}\nAll rights reserved.\n\nWeb: {4}\nTwitter: {5}\nEmail: {6}\n\n\
This program comes with ABSOLUTELY NO WARRANTY. For details, please visit\nhttp://www.gnu.org/licenses/gpl.html"
.format(__plugin_title__,
__version__,
__copyright_year__,
__author__,
__website__,
__twitter__,
__email__), c4d.GEMB_OK)
@staticmethod
def ESZipdir(path, zipObject, title):
"""Adds files to zip object.
:param string path: path of root directory
:param object zipObject: the zip object
:param string title: the name of the .fbx file with extension
"""
include = ['tex']
for root, dirs, files, in os.walk(path):
dirs[:] = [i for i in dirs if i in include]
for file in files:
if file.startswith('.'):
continue
if file.endswith('.fbx'.lower()) and file == title:
zipObject.write(os.path.join(root, file))
# zip textures in tex directory
texDir = os.path.join(path, 'tex')
if os.path.exists(texDir):
for f in os.listdir(texDir):
zipObject.write(os.path.join(path, 'tex', f))
class PublishModelThread(C4DThread):
"""Class that publishes 3D model to Sketchfab.com."""
def __init__(self, data, title, activeDoc, activeDocPath, enable_animation):
C4DThread.__init__(self)
self.data = data
self.title = title
self.activeDoc = activeDoc
self.activeDocPath = activeDocPath
self.enable_animation = enable_animation
def Main(self):
global g_uploaded
global g_error
# Need to work on this some more
time_start = datetime.datetime.now()
# t = time_start.strftime("%a %b %d %I:%M %p")
t = time_start.strftime("%c")
print("\nUpload started on {0}".format(t))
print("Exporting...\n")
exportFile = os.path.join(self.activeDocPath, self.title + '.fbx')
options = self.get_fbxexport_options()
backup_options = {}
export_options[c4d.FBXEXPORT_TRACKS] = self.enable_animation
export_options[c4d.FBXEXPORT_BAKE_ALL_FRAMES] = self.enable_animation
for key in export_options:
if options[key] != export_options[key]:
backup_options[key] = options[key]
options[key] = export_options[key]
# FBX Export
documents.SaveDocument(self.activeDoc, exportFile,
c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, FBX20142)
# restore options
for key in backup_options:
options[key] = backup_options[key]
if not os.path.exists(exportFile):
g_uploaded = False
g_error = "Export failed."
c4d.SpecialEventAdd(__plugin_id__)
return False
print("Export successful.")
basepath, dirname = os.path.split(self.activeDocPath)
archiveName = self.title + '.zip'
os.chdir(basepath)
zip = zipfile.ZipFile(archiveName, 'w')
Utilities.ESZipdir(dirname, zip, self.title+'.fbx')
zip.close()
self.data['fileModel'] = open(archiveName, 'rb')
# Connection code
# Begin upload
print("Uploading...\n")
try:
register_openers()
post_data, headers = multipart_encode(self.data)
req = urllib2.Request(SKETCHFAB_URL, post_data, headers, unverifiable=False)
response = urllib2.urlopen(url=req)
json_response = json.loads(str(response.read()))
if response and json_response["success"]:
model_id = json_response['result']['id']
response.close()
g_uploaded = True
# Open website on model page
result = gui.MessageDialog("Your model was succesfully uploaded to Sketchfab.com.\nClick OK to open the browser on your model page", c4d.GEMB_OKCANCEL)
if result == c4d.GEMB_R_OK:
Utilities.ESOpen_website(__sketchfab__ + '/models/' + model_id)
else:
g_error = "Invalid response from server."
except Exception as error:
g_uploaded = False
g_error = error
finally:
# Clean up
self.cleanup_files(archiveName, exportFile)
c4d.SpecialEventAdd(__plugin_id__)
def get_fbxexport_options(self):
''' Set the good options for fbx export to Sketchfab '''
# Get the fbx export plugin
fbxplugin = plugins.FindPlugin(1026370, c4d.PLUGINTYPE_SCENESAVER)
if not fbxplugin:
return
# Access the plugin options
reply = {}
if fbxplugin.Message(c4d.MSG_RETRIEVEPRIVATEDATA, reply):
return reply.get('imexporter')
def cleanup_files(self, archive_name=None, export_file=None):
if archive_name and os.path.exists(archive_name):
try:
os.remove(archive_name)
except Exception:
print("Unable to remove file {0}".format(archive_name))
if export_file and os.path.exists(export_file):
try:
os.remove(export_file)
except Exception:
print("Unable to remove file {0}".format(export_file))
class UserAreaPathsHeader(gui.GeUserArea):
"""Sketchfab header image."""
bmp = c4d.bitmaps.BaseBitmap()
def GetMinSize(self):
self.width = 600
self.height = 75
return (self.width, self.height)
def DrawMsg(self, x1, y1, x2, y2, msg):
thisFile = os.path.abspath(__file__)
thisDirectory = os.path.dirname(thisFile)
path = os.path.join(thisDirectory, "res", "header.png")
result, ismovie = self.bmp.InitWith(path)
x1 = 0
y1 = 0
x2 = self.bmp.GetBw()
y2 = self.bmp.GetBh()
if result == c4d.IMAGERESULT_OK:
self.DrawBitmap(self.bmp, 0, 0, self.bmp.GetBw(), self.bmp.GetBh(),
x1, y1, x2, y2, c4d.BMP_NORMALSCALED | c4d.BMP_ALLOWALPHA)
def Redraw(self):
thisFile = os.path.abspath(__file__)
thisDirectory = os.path.dirname(thisFile)
path = os.path.join(thisDirectory, "res", "header.png")
result, ismovie = self.bmp.InitWith(path)
x1 = 0
y1 = 0
x2 = self.bmp.GetBw()
y2 = self.bmp.GetBh()
if result == c4d.IMAGERESULT_OK:
self.DrawBitmap(self.bmp, 0, 0, self.bmp.GetBw(), self.bmp.GetBh(),
x1, y1, x2, y2, c4d.BMP_NORMALSCALED | c4d.BMP_ALLOWALPHA)
class MainDialog(gui.GeDialog):
"""Main Dialog Class"""
userarea_paths_header = UserAreaPathsHeader()
save_api_token = False
def InitValues(self):
"""Called when the dialog is initialized by the GUI.
True if successful, or False to signalize an error.
"""
global g_lastUpdated
print("\n{0} v{1} loaded. Copyright (C) {2} {3}. All rights reserved.\n\n\
This program comes with ABSOLUTELY NO WARRANTY. For details, please visit http://www.gnu.org/licenses/gpl.html\n\n"
.format(__plugin_title__, __version__, __copyright_year__, __author__))
try:
prefs = shelve.open(FILEPATH, 'r')
if 'api_token' in prefs:
if prefs['api_token']:
self.MenuInitString(MENU_SAVE_API_TOKEN, True, True)
self.save_api_token = True
self.SetString(EDITXT_API_TOKEN, '-' * len(prefs['api_token']))
else:
self.MenuInitString(MENU_SAVE_API_TOKEN, True, False)
self.save_api_token = False
if 'lastUpdate' in prefs:
g_lastUpdated = prefs['lastUpdate']
self.groupSixWillRedraw()
prefs.close()
except:
self.MenuInitString(MENU_SAVE_API_TOKEN, True, False)
self.Enable(EDITXT_PASSWORD, False)
return True
def createGroupFiveItems(self):
self.AddCheckbox(id=CHK_PRIVATE, flags=c4d.BFH_SCALEFIT | c4d.BFH_LEFT,
initw=0, inith=0, name="Private Model (Pro User Only)")
self.AddStaticText(id=0, flags=c4d.BFH_LEFT,
initw=0, inith=0, name="Password (optional): ")
self.AddEditText(id=EDITXT_PASSWORD, flags=c4d.BFH_SCALEFIT,
initw=0, inith=0, editflags=c4d.EDITTEXT_PASSWORD)
self.AddCheckbox(id=CHK_PUBLISHDRAFT, flags=c4d.BFH_LEFT,
initw=0, inith=0, name="Publish as a draft (not visible to public immediately)")
def groupFiveWillRedraw(self):
self.LayoutFlushGroup(GROUP_FIVE)
self.createGroupFiveItems()
self.LayoutChanged(GROUP_FIVE)
def createGroupSixItems(self):
self.AddStaticText(id=0, flags=c4d.BFH_LEFT | c4d.BFH_SCALEFIT, initw=0, inith=0, name=g_lastUpdated)
self.AddButton(id=BTN_PUBLISH, flags=c4d.BFH_RIGHT | c4d.BFV_BOTTOM, initw=75, inith=16, name="Publish")
def groupSixWillRedraw(self):
self.LayoutFlushGroup(GROUP_SIX)
self.createGroupSixItems()
self.LayoutChanged(GROUP_SIX)
def CreateLayout(self):
"""Override - Called when C4D is about to display the dialog.
True if successful, or False to signalize an error.
"""
self.SetTitle(__plugin_title__)
# Create the menu
self.MenuFlushAll()
# Options menu
self.MenuSubBegin("File")
self.MenuAddCommand(c4d.IDM_CM_CLOSEWINDOW)
self.MenuSubEnd()
# Options menu
self.MenuSubBegin("Options")
self.MenuAddString(MENU_SAVE_API_TOKEN, "Save API token")
self.MenuSubEnd()
# Info menu
self.MenuSubBegin("Info")
self.MenuAddString(BTN_ABOUT, "About")
self.MenuAddString(BTN_WEB, "Visit Sketchfab.com")
self.MenuAddString(BTN_WEB_990, "Visit 990adjustments.com")
self.MenuSubEnd()
self.MenuFinished()
docname = documents.GetActiveDocument().GetDocumentName()
# ----------------------------------------------------------------------
# Begin WRAPPER
# ----------------------------------------------------------------------
self.GroupBegin(id=GROUP_WRAPPER,
flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT,
cols=1,
rows=1,
title="Wrapper",
groupflags=c4d.BORDER_NONE)
# UA groups
self.GroupBegin(id=GROUP_ONE,
flags=c4d.BFH_SCALEFIT,
cols=1,
rows=1,
title="Header",
groupflags=c4d.BORDER_NONE)
self.GroupSpace(0, 0)
self.GroupBorderSpace(0, 0, 0, 0)
self.AddUserArea(UA_HEADER, c4d.BFH_LEFT)
self.AttachUserArea(self.userarea_paths_header, UA_HEADER)
self.userarea_paths_header.LayoutChanged()
self.GroupEnd()
self.GroupBegin(id=GROUP_TWO,
flags=c4d.BFH_SCALEFIT,
cols=2,
rows=1)
self.GroupSpace(40, 10)
self.GroupBorderSpace(6, 6, 6, 6)
self.AddStaticText(id=TXT_MODEL_NAME, flags=c4d.BFH_LEFT, initw=0, inith=0, name="Model name:")
self.AddEditText(id=EDITXT_MODEL_TITLE, flags=c4d.BFH_SCALEFIT, initw=0, inith=0)
self.SetString(EDITXT_MODEL_TITLE, docname)
self.AddStaticText(id=TXT_DESCRIPTION, flags=c4d.BFH_LEFT | c4d.BFV_TOP,
initw=0, inith=0, name="Description:")
self.AddMultiLineEditText(id=EDITXT_DESCRIPTION, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT,
initw=0, inith=100, style=c4d.DR_MULTILINE_WORDWRAP)
self.SetString(EDITXT_DESCRIPTION, docname)
self.AddStaticText(id=TXT_TAGS, flags=c4d.BFH_LEFT, initw=0, inith=0, name="Tags: cinema4d ")
self.AddEditText(id=EDITXT_TAGS, flags= c4d.BFH_RIGHT | c4d.BFH_SCALEFIT, initw=0, inith=0)
self.AddCheckbox(id=CHK_ANIMATION, flags=c4d.BFH_LEFT,
initw=0, inith=0, name="Enable animation")
self.GroupEnd()
self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)
self.GroupBegin(id=GROUP_FOUR,
flags=c4d.BFH_SCALEFIT,
cols=4,
rows=1)
self.GroupSpace(11, 10)
self.GroupBorderSpace(6, 6, 6, 6)
self.AddStaticText(id=TXT_API_TOKEN, flags=c4d.BFH_LEFT, initw=0, inith=0, name="API token:")
self.AddEditText(id=EDITXT_API_TOKEN,flags=c4d.BFH_SCALEFIT,
initw=230, inith=0, editflags=c4d.EDITTEXT_PASSWORD)
self.AddButton(id=BTN_SKFB_TOKEN, flags=c4d.BFH_RIGHT, initw=145, inith=16, name="Get API token")
self.AddButton(id=BTN_SKFB_SIGNUP, flags=c4d.BFH_RIGHT, initw=130, inith=16, name="Create account")
self.GroupEnd()
self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)
# Group FIVE
self.GroupBegin(id=GROUP_FIVE,
flags=c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM,
cols=3,
rows=1)
self.GroupSpace(4, 4)
self.GroupBorderSpace(6, 6, 6, 6)
self.groupFiveWillRedraw()
self.GroupEnd()
self.AddSeparatorH(inith=0, flags=c4d.BFH_FIT)
self.GroupBegin(id=GROUP_SIX,
flags=c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM,
cols=2,
rows=1)
self.GroupSpace(4, 4)
self.GroupBorderSpace(6, 6, 6, 6)
self.groupSixWillRedraw()
self.GroupEnd()
self.GroupEnd()
# ----------------------------------------------------------------------
# End WRAPPER
# ----------------------------------------------------------------------
return True
def setApiToken(self, _setApiToken, _api_token=None):
"""Saves API token.
:param string _setApiToken: the api token
:param bool _api_token: save or delete api token
"""
if _setApiToken:
try:
prefs = shelve.open(FILEPATH, 'c')
prefs['api_token'] = _api_token
prefs.close()
except Exception, err:
print("Could not save API token. Reason: {0}".format(err))
else:
# delete settings
try:
os.remove(FILEPATH + '.db')
self.SetString(EDITXT_API_TOKEN, "")
except Exception, err:
print("Unable to delete settings. Reason: {0}".format(err))
def CoreMessage(self, id, msg):
"""Override this function if you want to react
to C4D core messages. The original message is stored in msg.
"""
global g_lastUpdated
if id == __plugin_id__:
c4d.StatusSetBar(100)
time_start = datetime.datetime.now()
# t = time_start.strftime("%a %b %d %I:%M %p")
t = time_start.strftime("%c")
try:
prefs = shelve.open(FILEPATH, 'c')
except Exception as err:
print("\nUnable to load preferences. Reason: ".format(err))
if g_uploaded:
print("Your model was succesfully uploaded to Sketchfab.com.")
print("\nUpload ended on {0}".format(t))
g_lastUpdated = "Successful Upload on {0}".format(t)
if prefs:
prefs['lastUpdate'] = g_lastUpdated
prefs.close()
else:
gui.MessageDialog("Unable to upload model to Sketchfab.com. Reason: {0}".format(g_error), c4d.GEMB_OK)
print("Unable to upload model to Sketchfab.com. Reason: {0}".format(g_error))
g_lastUpdated = "Upload failed on {0}".format(t)
if prefs:
prefs['lastUpdate'] = g_lastUpdated
prefs.close()
self.groupSixWillRedraw()
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return True
def Command(self, id, msg):
"""Override this function if you want to react to user clicks. Whenever the
user clicks on a gadget and/or changes its value this function will be
called.
It is also called when a string menu item is selected.
Override it to handle such events.
"""
global g_lastUpdated
if id == MENU_SAVE_API_TOKEN:
if self.save_api_token:
self.MenuInitString(MENU_SAVE_API_TOKEN, True, False)
self.save_api_token = False
self.setApiToken(False)
else:
self.MenuInitString(MENU_SAVE_API_TOKEN, True, True)
self.save_api_token = True
if id == BTN_ABOUT:
Utilities.ESOpen_about()
if id == BTN_WEB:
Utilities.ESOpen_website(__sketchfab__)
if id == BTN_WEB_990:
Utilities.ESOpen_website(__website__)
if id == BTN_THUMB_SRC_PATH:
selected = storage.LoadDialog(type=c4d.FILESELECTTYPE_ANYTHING)
if not selected:
return False
else:
self.SetString(EDITXT_THUMB_SRC_PATH, selected)
if id == BTN_SKFB_TOKEN:
Utilities.ESOpen_website(__sketchfab__ + '/settings/password')
if id == BTN_SKFB_SIGNUP:
Utilities.ESOpen_website(__sketchfab__ + '/signup')
if id == CHK_PRIVATE:
if self.GetBool(CHK_PRIVATE):
self.Enable(EDITXT_PASSWORD, True)
else:
self.groupFiveWillRedraw()
self.Enable(EDITXT_PASSWORD, False)
if id == BTN_PUBLISH:
c4d.StatusSetBar(50)
g_lastUpdated = "Working it..."
self.groupSixWillRedraw()
data = {}
activeDoc = documents.GetActiveDocument()
activeDocPath = activeDoc.GetDocumentPath()
if not os.path.exists(activeDocPath):
path = c4d.storage.SaveDialog(type=c4d.FILESELECTTYPE_ANYTHING, title="Please save your scene", force_suffix="c4d")
result = c4d.documents.SaveDocument(activeDoc,path, c4d.SAVEDOCUMENTFLAGS_0, c4d.FORMAT_C4DEXPORT)
c4d.documents.LoadFile(path)
if not result:
gui.MessageDialog("Please save your scene first.", c4d.GEMB_OK)
c4d.StatusClear()
return False
# Set document data with newly saved document
activeDoc = documents.GetActiveDocument()
activeDocPath = activeDoc.GetDocumentPath()
self.Enable(BTN_PUBLISH, False)
self.SetTitle("{0} publishing model...".format(__plugin_title__))
title = self.GetString(EDITXT_MODEL_TITLE)
description = self.GetString(EDITXT_DESCRIPTION)
tags = self.GetString(EDITXT_TAGS)
token = self.GetString(EDITXT_API_TOKEN)
private = self.GetBool(CHK_PRIVATE)
password = self.GetString(EDITXT_PASSWORD)
enable_animation = self.GetBool(CHK_ANIMATION)
auto_publish = not(self.GetBool(CHK_PUBLISHDRAFT))
if '-' in token:
try:
prefs = shelve.open(FILEPATH, 'r')
except:
gui.MessageDialog("Please re-enter your API token.", c4d.GEMB_OK)
self.MenuInitString(MENU_SAVE_API_TOKEN, True, False)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
else:
if 'api_token' in prefs:
if prefs['api_token']:
api_token = prefs['api_token']
else:
gui.MessageDialog("Please re-enter your API token.", c4d.GEMB_OK)
self.MenuInitString(MENU_SAVE_API_TOKEN, True, False)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
prefs.close()
else:
api_token = token
if len(title) == 0:
gui.MessageDialog("Please enter a name for your model.", c4d.GEMB_OK)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
if len(title) > 32:
gui.MessageDialog("The model name should not have more than 32 characters.", c4d.GEMB_OK)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
if len(api_token) == 0:
gui.MessageDialog("Please enter your API token. \
Your API token can be found in your dashboard at sketchfab.com", c4d.GEMB_OK)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
if (len(description) > 1024):
gui.MessageDialog("Please use a description with less than 1024 characters", c4d.GEMB_OK)
self.Enable(BTN_PUBLISH, True)
self.SetTitle(__plugin_title__)
c4d.StatusClear()
return False
# populate data
if len(description) != 0:
data['description'] = description
data['tags'] = 'cinema4d '
if len(tags) != 0:
data['tags'] += tags
data['title'] = title
data['token'] = api_token
if private:
data['private'] = private
if private and len(password) != 0:
data['password'] = password
if self.save_api_token:
self.setApiToken(True, api_token)
# Start Multithread operations
# pass on data
data['source'] = 'cinema4d'
data['isPublished'] = auto_publish
self.publish = PublishModelThread(data, title, activeDoc, activeDocPath, enable_animation)
self.publish.Start()
self.publish.Wait(True)
return True
class SketchfabExporter(plugins.CommandData):
"""Plugin class"""
dialog = None
def Execute(self, doc):
# Check C4D version
if c4d.GetC4DVersion() < 15000 and c4d.GeGetCurrentOS() == c4d.OPERATINGSYSTEM_WIN:
c4d.gui.MessageDialog("Sorry, but the plugin is incompatible with the version of Cinema 4D you are currently running.\n\n\
The Sketchfab plugin for Windows requires\nCinema 4D R15 or greater.", c4d.GEMB_OK)
return False
if self.dialog is None:
self.dialog = MainDialog()
return self.dialog.Open(dlgtype=c4d.DLG_TYPE_ASYNC,
pluginid=__plugin_id__,
defaultw=600,
defaulth=450)
def RestoreLayout(self, sec_ref):
if self.dialog is None:
self.dialog = MainDialog()
return self.dialog.Restore(pluginid=__plugin_id__, secret=sec_ref)
if __name__ == "__main__":
icon = bitmaps.BaseBitmap()
dir, file = os.path.split(__file__)
iconPath = os.path.join(dir, "res", "icon.png")
icon.InitWith(iconPath)
plugins.RegisterCommandPlugin(id=__plugin_id__,
str=__plugin_title__,
info=0,
help=HELP_TEXT,
dat=SketchfabExporter(),
icon=icon)