Sepehr Taghdisian avatar Sepehr Taghdisian committed f129387

clip editor update, waf build update

Comments (0)

Files changed (15)

include/engine/cmp-types.h

 	CMP_OBJTYPE_LIGHT = (1<<2), /**< Light objects, must have "light" component */
 	CMP_OBJTYPE_DECAL = (1<<3), /**< Decal objects, must have "decal" component */
 	CMP_OBJTYPE_CAMERA = (1<<4), /**< Camera object, must have "camera" component */
-    CMP_OBJTYPE_TRIGGER = (1<<5) /**< Trigger object, must have "trigger" component */
+    CMP_OBJTYPE_TRIGGER = (1<<5), /**< Trigger object, must have "trigger" component */
+    CMP_OBJTYPE_ENV = (1<<6) /**< Environmental objects like terrain, sky, ocean, etc.. */
 };
 
 /**

include/engine/components/cmp-anim.h

 void cmp_anim_reload(const char* filepath, reshandle_t hdl, uptr_t param1, uptr_t param2);
 
 ENGINE_API uint32 cmp_anim_getframecnt(cmphandle_t hdl);
+ENGINE_API uint32 cmp_anim_getfps(cmphandle_t hdl);
 ENGINE_API void cmp_anim_play(cmphandle_t hdl);
 ENGINE_API void cmp_anim_stop(cmphandle_t hdl);
 ENGINE_API bool_t cmp_anim_isplaying(cmphandle_t hdl);
 ENGINE_API uint32 cmp_anim_getcurframe(cmphandle_t hdl);
+ENGINE_API uint32 cmp_anim_getclipcnt(cmphandle_t hdl);
+ENGINE_API const char* cmp_anim_getclipname(cmphandle_t hdl, uint32 clip_idx);
 
 
 #endif /* __CMPANIM_H__ */

src/engine/components/cmp-anim.c

 uint32 cmp_anim_getcurframe(cmphandle_t hdl)
 {
     struct cmp_anim* a = cmp_getinstancedata(hdl);
+    if (a->frame_idx != INVALID_INDEX)
+        return a->frame_idx;
+
     if (a->clip_hdl != INVALID_HANDLE)  {
         struct anim_clip* clip = rs_get_anim(a->clip_hdl);
         return clampun((uint32)(a->t/clip->ft), 0, clip->frame_cnt-1);
         return 0;
     }
 }
+
+uint32 cmp_anim_getfps(cmphandle_t hdl)
+{
+    struct cmp_anim* a = cmp_getinstancedata(hdl);
+    if (a->clip_hdl != INVALID_HANDLE)  {
+        struct anim_clip* clip = rs_get_anim(a->clip_hdl);
+        return clip->fps;
+    }   else    {
+        return 0;
+    } 
+}
+
+uint32 cmp_anim_getclipcnt(cmphandle_t hdl)
+{
+    struct cmp_anim* a = cmp_getinstancedata(hdl);
+    if (a->clip_hdl != INVALID_HANDLE)  {
+        struct anim_clip* clip = rs_get_anim(a->clip_hdl);
+        return clip->subclip_cnt;
+    }    else   {
+        return 0;
+    }
+}
+
+const char* cmp_anim_getclipname(cmphandle_t hdl, uint32 clip_idx)
+{
+    struct cmp_anim* a = cmp_getinstancedata(hdl);
+    if (a->clip_hdl != INVALID_HANDLE)  {
+        struct anim_clip* clip = rs_get_anim(a->clip_hdl);
+        ASSERT(clip_idx , clip->subclip_cnt);
+        return clip->subclips[clip_idx].name;
+    }    else   {
+        return "";
+    }
+}
     rpath.resize_fn = gfx_deferred_resize;
 
     rpflags = GFX_RPATH_RAW | GFX_RPATH_ALPHAMAP | GFX_RPATH_DIFFUSEMAP | GFX_RPATH_NORMALMAP |
-        GFX_RPATH_SKINNED | GFX_RPATH_ALPHAMAP;
+        GFX_RPATH_SKINNED;
     r = gfx_rpath_register(CMP_OBJTYPE_MODEL, rpflags, &rpath);
     if (IS_FAIL(r))
         return FALSE;

src/engine/pybind/dheng.py

 def cmp_anim_getcurframe(*args):
   return _dheng.cmp_anim_getcurframe(*args)
 cmp_anim_getcurframe = _dheng.cmp_anim_getcurframe
+
+def cmp_anim_getfps(*args):
+  return _dheng.cmp_anim_getfps(*args)
+cmp_anim_getfps = _dheng.cmp_anim_getfps
 # This file is compatible with both classic and new-style classes.
 
 

src/engine/pybind/pyengine.i

 void cmp_anim_stop(cmphandle_t hdl);
 bool_t cmp_anim_isplaying(cmphandle_t hdl);
 uint32 cmp_anim_getcurframe(cmphandle_t hdl);
+uint32 cmp_anim_getfps(cmphandle_t hdl);

src/engine/pybind/pyengine_wrap.c

 }
 
 
+SWIGINTERN PyObject *_wrap_cmp_anim_getfps(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  cmphandle_t arg1 ;
+  unsigned long long val1 ;
+  int ecode1 = 0 ;
+  PyObject * obj0 = 0 ;
+  uint32 result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:cmp_anim_getfps",&obj0)) SWIG_fail;
+  ecode1 = SWIG_AsVal_unsigned_SS_long_SS_long(obj0, &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "cmp_anim_getfps" "', argument " "1"" of type '" "cmphandle_t""'");
+  } 
+  arg1 = (cmphandle_t)(val1);
+  result = (uint32)cmp_anim_getfps(arg1);
+  resultobj = SWIG_From_unsigned_SS_int((unsigned int)(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
 	 { (char *)"core_init", _wrap_core_init, METH_VARARGS, NULL},
 	 { (char *)"cmp_anim_stop", _wrap_cmp_anim_stop, METH_VARARGS, NULL},
 	 { (char *)"cmp_anim_isplaying", _wrap_cmp_anim_isplaying, METH_VARARGS, NULL},
 	 { (char *)"cmp_anim_getcurframe", _wrap_cmp_anim_getcurframe, METH_VARARGS, NULL},
+	 { (char *)"cmp_anim_getfps", _wrap_cmp_anim_getfps, METH_VARARGS, NULL},
 	 { NULL, NULL, 0, NULL }
 };
 

src/engine/wscript

         "components/cmp-model.c",
         "components/cmp-rbody.c",
         "components/cmp-trigger.c",
-        "components/cmp-xform.c"])
+        "components/cmp-xform.c",
+        'components/cmp-anim.c'])
         
     # lua
     files.extend([

src/h3dimport-gui/clipedit.py

         layout = QtGui.QVBoxLayout()
         self.setLayout(layout)
 
+        lbl_framecnt = QtGui.QLabel('frame-cnt: ', self)
+        layout.addWidget(lbl_framecnt)
+
+        imgpath = os.path.normcase(util.get_exec_dir(__file__) + '/img/')
         layout2 = QtGui.QHBoxLayout()
         layout2.setSpacing(1)
         ed_name = QtGui.QLineEdit(self)
         ed_name.setMaxLength(30)
         layout2.addWidget(ed_name)
-        btn_add = QtGui.QPushButton('+', self)
-        btn_remove = QtGui.QPushButton('-', self)
+        btn_add = QtGui.QPushButton(self)
+        btn_remove = QtGui.QPushButton(self)
+        btn_add.setIcon(QtGui.QIcon(imgpath + 'glyphicons_432_plus.png'))
+        btn_remove.setIcon(QtGui.QIcon(imgpath + 'glyphicons_207_remove_2.png'))
         btn_add.setFixedSize(24, 24)
         btn_remove.setFixedSize(24, 24)
         layout2.addWidget(btn_add)
         layout2.addWidget(btn_remove)
         layout.addLayout(layout2)
 
+        self.lbl_framecnt = lbl_framecnt
         self.ed_name = ed_name
         self.btn_remove = btn_remove
         self.btn_add = btn_add
         self.lst_clips = QtGui.QListWidget(self)
         self.lst_clips.setMaximumHeight(150)
         lst_palette = self.lst_clips.palette()
-        lst_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Highlight, \
+        lst_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Highlight,
             lst_palette.brush(QtGui.QPalette.Active, QtGui.QPalette.Highlight))
-        lst_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.HighlightedText, \
+        lst_palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.HighlightedText,
             lst_palette.brush(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
         self.lst_clips.setPalette(lst_palette)
 
     def set_item(self):
         pass
 
+    def load_clips(self, clips_jsonfile):
+        jclips = json.loads(open(clips_jsonfile, 'r').read())
+
+        # fill the data
+        if not jclips:  return
+
+        for i in range(0, len(jclips)):
+            # set default values
+            if 'start' not in jclips[i]:     jclips[i]['start'] = 0
+            if 'end' not in jclips[i]:       jclips[i]['end'] = self.frame_cnt
+            if 'looped' not in jclips[i]:    jclips[i]['looped'] = False
+            self.clips.append(jclips[i])
+
+        # fill the list
+        for clip in self.clips:
+            self.lst_clips.addItem(clip['name'])
+
+    def save_clips(self, clips_jsonfile):
+        open(clips_jsonfile, 'w').write(json.dumps(self.clips, indent=4))
+
     def ed_start_changed(self, text):
         row = self.lst_clips.currentRow()
-        if row != -1:
+        if row != -1 and text != '':
             self.clips[row]['start'] = max(0, int(str(text)))
     def ed_end_changed(self, text):
         row = self.lst_clips.currentRow()
-        if row != -1:
+        if row != -1 and text != '':
             self.clips[row]['end'] = min(int(str(text)), self.frame_cnt)
     def chk_looped_changed(self, state):
         row = self.lst_clips.currentRow()
 
     def set_framecnt(self, framecnt):
         self.frame_cnt = framecnt
+        self.lbl_framecnt.setText('frame-cnt: {0}'.format(framecnt))
 
     def ed_name_changed(self, text):
         if text.count() > 0:
                     return
         else:
             self.btn_add.setEnabled(False)
+            self.btn_remove.setEnabled(False)
             self.lst_clips.setCurrentRow(-1)
             self.reset_controls()
 
+    def preview_clip(self, clip):
+        parent = self.parent()
+        if parent.btn_play_state:
+            parent.play_stop()
+
+        parent.btn_play.setIcon(parent.icn_pause)
+
+        # initialize playing (manual)
+        parent.preview_clip = clip
+        parent.preview_frame = clip['start']
+        parent.tm_preview.start()            
+
     def lst_clips_selected(self):
         self.btn_remove.setEnabled(True)
         row = self.lst_clips.currentRow()
         if row != -1:
             for widget in self.edit_widgets: widget.setEnabled(True)
             self.update_controls(self.clips[row])
+            self.preview_clip(self.clips[row])
 
     def lst_clips_clicked(self, item):
         self.lst_clips_selected()
         self.edit_widgets[0].setFocus()
 
         # add to clips
-        self.clips.append({\
+        self.clips.append({ \
             'name': str(self.ed_name.text()), \
             'start': min(self.clips[-1]['end'] + 1, self.frame_cnt) if len(self.clips)>0 else 0, \
             'end': self.frame_cnt, \
         if selected_id != -1: 
             self.lst_clips.removeItemWidget(self.lst_clips.takeItem(selected_id))
             self.reset_controls()
+            self.parent().play_stop()
             del self.clips[selected_id]
 
 class qClipController(QtGui.QWidget):
         self.tick_sz = 1
         self.frame_cnt = 60
         self.frame_cursor = 0 # current frame number
+        self.frame_cursor_start = 0
         self.frame_cursor_end = 0
         self.frame_cursor_prev = 0
         self.setMinimumHeight(24)
         self.setMouseTracking(True)
         self.anim_cmp = None
+        self.mouse_dwn = False
 
-        self.mouse_dwn = False
+    def deselect(self):
+        self.frame_cursor_start = self.frame_cursor_end = self.frame_cursor
 
     def calc_frame_x(self, n, w):
         return int(math.floor(n * w / self.frame_cnt))
         start_x = 2
 
         ## selection
-        if self.frame_cursor < self.frame_cursor_end:
-            x = start_x + self.calc_frame_x(self.frame_cursor, w)
+        if self.frame_cursor_start < self.frame_cursor_end:
+            x = start_x + self.calc_frame_x(self.frame_cursor_start, w)
             qp.fillRect(x, 3, \
                 self.calc_frame_x(self.frame_cursor_end, w) - x + 1, h - 3, \
                 QtGui.QBrush(QtGui.QColor(70, 150, 70), QtCore.Qt.Dense4Pattern))
         qp.drawLine(QtCore.QLine(start_x + cursor_x, max(0, h-3), start_x + cursor_x, 3))
 
         ## frame index
-        if self.frame_cursor == self.frame_cursor_end:
+        if self.frame_cursor_start == self.frame_cursor_end:
             ftext = str(self.frame_cursor)
             text_offset = 0
         else:
-            ftext = str(self.frame_cursor) + '-' + str(self.frame_cursor_end)
+            ftext = str(self.frame_cursor_start) + '-' + str(self.frame_cursor_end)
             text_offset = 16
         qp.setBackground(QtGui.QColor(200, 0, 0))
         qp.setBackgroundMode(QtCore.Qt.OpaqueMode)
             if e.modifiers() & QtCore.Qt.ShiftModifier:
                 self.frame_cursor_end = self.calc_frame_n(cursor_x, w)
                 dheng.cmp_modifyui(self.anim_cmp, 'frame_idx', self.frame_cursor_end)
-                if self.frame_cursor > self.frame_cursor_end:
+                if self.frame_cursor_start > self.frame_cursor_end:
                     tmp = self.frame_cursor_end
-                    self.frame_cursor_end = self.frame_cursor
-                    self.frame_cursor = tmp
+                    self.frame_cursor_end = self.frame_cursor_start
+                    self.frame_cursor_start = tmp
             else:
                 self.frame_cursor = self.calc_frame_n(cursor_x, w)
+                self.frame_cursor_start = self.frame_cursor
                 self.frame_cursor_end = self.frame_cursor
                 dheng.cmp_modifyui(self.anim_cmp, 'frame_idx', self.frame_cursor)
 
             else:
                 self.frame_cursor = self.calc_frame_n(cursor_x, w)
                 self.frame_cursor_end = self.frame_cursor
+                self.frame_cursor_start = self.frame_cursor
                 dheng.cmp_modifyui(self.anim_cmp, 'frame_idx', self.frame_cursor)
 
             self.update()
 
     def set_frame(self, f):
         if f != self.frame_cursor:
-            if self.frame_cursor == self.frame_cursor_end:
-                self.frame_cursor_end = f
+            if self.frame_cursor_start == self.frame_cursor_end:
+                self.frame_cursor_start = self.frame_cursor_end = f
             self.frame_cursor = f 
             self.update()
 
         self.setSizeGripEnabled(True)
 
         exedir = util.get_exec_dir(__file__)
-        self.icn_play = QtGui.QIcon(os.path.normcase(exedir + '/' + 'img/glyphicons_173_play.png'))
-        self.icn_pause = QtGui.QIcon(os.path.normcase(exedir + '/' + 'img/glyphicons_174_pause.png'))
+        self.icn_play = QtGui.QIcon(os.path.normcase(exedir + '/img/glyphicons_173_play.png'))
+        self.icn_pause = QtGui.QIcon(os.path.normcase(exedir + '/img/glyphicons_174_pause.png'))
 
         layout = QtGui.QVBoxLayout()
 
         layout3 = QtGui.QHBoxLayout()
         self.btn_play = QtGui.QPushButton(self)
         self.btn_play.setIcon(self.icn_play)
-        self.btn_play_state = False # keeps playing state of 'play/pause' butto
+        self.btn_play_state = False # keeps playing state of 'play/pause' button
         self.btn_play_state_prev = False
 
         self.clip_ctrl = qClipController(self)
         self.tm_play = QtCore.QTimer(self)
         self.tm_play.setInterval(20)
 
+        self.tm_preview = QtCore.QTimer(self)
+        self.tm_preview.setInterval(33)
+        self.preview_clip = {}
+        self.preview_frame = 0
+
         # events
         self.btn_play.clicked.connect(self.btn_play_clicked)
         self.tm_play.timeout.connect(self.tm_play_timeout)
+        self.tm_preview.timeout.connect(self.tm_preview_timeout)
+
+    def tm_preview_timeout(self):
+         dheng.cmp_modifyui(self.anim_cmp, 'frame_idx', self.preview_frame)
+         self.clip_ctrl.set_frame(self.preview_frame)
+         self.preview_frame += 1
+         if self.preview_frame > self.preview_clip['end'] - 1:
+            if not self.preview_clip['looped']:
+                self.play_stop()
+            else:
+                self.preview_frame = self.preview_clip['start']
 
     def tm_play_timeout(self):
         if self.anim_cmp:   
                 else:                       
                     self.btn_play.setIcon(self.icn_pause)
             self.btn_play_state_prev = self.btn_play_state
-
             self.clip_ctrl.set_frame(dheng.cmp_anim_getcurframe(self.anim_cmp))
 
     def play_stop(self):
         self.btn_play.setIcon(self.icn_play)
         self.tm_play.stop()
+        self.tm_preview.stop()
         dheng.cmp_anim_stop(self.anim_cmp)
 
     def btn_play_clicked(self, checked):
+        # normal play, play from the start
         if not self.btn_play_state:
-            dheng.cmp_anim_play(self.anim_cmp)
-            self.tm_play.start()
+            # custom play (range is selected), we play the range in loop mode
+            if self.clip_ctrl.frame_cursor_start != self.clip_ctrl.frame_cursor_end:
+                self.preview_frame = self.clip_ctrl.frame_cursor_start
+                self.preview_clip = {'start': self.clip_ctrl.frame_cursor_start, 
+                    'end': self.clip_ctrl.frame_cursor_end,
+                    'looped': True}
+                self.tm_preview.start()
+            else:
+                dheng.cmp_anim_play(self.anim_cmp)
+                self.tm_play.start()
             self.btn_play.setIcon(self.icn_pause)
         else:
-            dheng.cmp_anim_stop(self.anim_cmp)
+            if self.clip_ctrl.frame_cursor_start != self.clip_ctrl.frame_cursor_end:
+                self.tm_preview.stop()
+                self.preview_frame = self.clip_ctrl.frame_cursor_start
+            else:
+                self.tm_play.stop()
+                dheng.cmp_anim_stop(self.anim_cmp)
+
             self.btn_play.setIcon(self.icn_play)
-            self.tm_play.stop()
+
         self.btn_play_state = not self.btn_play_state
         self.btn_play_state_prev = self.btn_play_state
 
-
     def closeEvent(self, e):
         self.unload_props()
+        self.tm_preview.stop()
+        self.tm_play.stop()
         e.accept()
 
-    def load_props(self, model_file, anim_file):
+    def load_props(self, model_file, anim_file, clips_jsonfile):
         self.eng_view.set_cam(engine.camera)
 
         # ground
         ground = dheng.scn_create_obj(dheng.scn_getactive(), 'ground', dheng.CMP_OBJTYPE_MODEL)
-        dheng.cmp_modifys(dheng.cmp_findinstance_inobj(ground, 'model'), 'model_file', \
+        dheng.cmp_modifys(dheng.cmp_findinstance_inobj(ground, 'model'), 'model_file',
             'test-data/plane.h3dm')
         ## 
         obj = dheng.scn_create_obj(dheng.scn_getactive(), 'test', dheng.CMP_OBJTYPE_MODEL)
         dheng.cmp_modifys(anim_cmp, 'anim_file', anim_file)
         dheng.cmp_anim_stop(anim_cmp)
 
-        self.clip_ctrl.set_framecnt(dheng.cmp_anim_getframecnt(anim_cmp))
+        frame_cnt = dheng.cmp_anim_getframecnt(anim_cmp)
+        self.clip_ctrl.set_framecnt(frame_cnt)
         self.clip_ctrl.anim_cmp = anim_cmp
+        self.wnd_clips.set_framecnt(frame_cnt)
 
         self.obj = obj
         self.ground = ground
         self.anim_cmp = anim_cmp
 
+        self.wnd_clips.load_clips(clips_jsonfile)
+        self.tm_preview.setInterval(1000/dheng.cmp_anim_getfps(anim_cmp))
+        self.clips_jsonfile = clips_jsonfile
+
     def unload_props(self):
         if self.obj:        dheng.scn_destroy_obj(self.obj)
         if self.ground:     dheng.scn_destroy_obj(self.ground)
+        self.wnd_clips.save_clips(self.clips_jsonfile)
         self.obj = None
         self.ground = None
         self.anim_cmp = None

src/h3dimport-gui/h3dimport-gui.py

         
         # make controls
         self.edit_infilepath = QtGui.QLineEdit(self)
+        self.edit_infilepath.setReadOnly(True)
         btn_browse_infile = QtGui.QPushButton("Browse", self)
         btn_browse_infile.setFixedWidth(60)
         self.edit_outfilepath = QtGui.QLineEdit(self)
         else:
             # get model file from the current imported model
             global main_wnd
+
+            # before anything, do the animation import process
+            self.import_clicked()
+
             model_file = str(main_wnd.wnds['model'].edit_outfilepath.text())
             anim_file = str(self.edit_outfilepath.text())
-            self.dlg_clipedit.load_props(model_file, anim_file)
+            self.dlg_clipedit.load_props(model_file, anim_file, self.in_jsonfile)
             self.dlg_clipedit.exec_()
 
+    def init_clips_jsonfile(self):
+        global prefs
+        in_filepath = str(self.edit_infilepath.text())
+        in_jsonfile = util.make_samefname(in_filepath, in_filepath, '.json')
+        if not os.path.isfile(in_jsonfile):
+            # create an empty json clips file
+            open(in_jsonfile, 'w').write('[{"name":"all"}]')
+        self.in_jsonfile = in_jsonfile
+
     def browse_infile_clicked(self):
         dlg = QtGui.QFileDialog(self, "Open animation", self.infiledir, \
             "Animation files (*.dae *.obj *.x *.ase *.ms3d)")
             in_filepath = str(self.edit_infilepath.text())
             out_filepath = str(self.edit_outfilepath.text())
             self.edit_outfilepath.setText(util.make_samefname(out_filepath, in_filepath, "h3da"))
-        
+
+            # try to locate clip (json) file in the same directory and same name as input file, 
+            # if not found, create an empty
+            self.init_clips_jsonfile()
+
     def browse_outfile_clicked(self):
         dlg = QtGui.QFileDialog(self, "Save h3da file", self.outfiledir, \
             "dark-hammer anims (*.h3da)")
         args = [prefs['binpath'], 
                 "-a", str(self.edit_infilepath.text()),
                 "-o", os.path.normcase(prefs['assetdir'] + '/' + str(self.edit_outfilepath.text())),
-                "-fps", str(self.edit_fps.text())]
+                "-fps", str(self.edit_fps.text()),
+                '-clips', self.in_jsonfile]
         if prefs['verbose']:
             args.extend(["-v"])
         if self.check_zup.isChecked():
         self.outfiledir = cfg.get("anim", "out_filedir")
         self.edit_fps.setText(cfg.get("anim", "fps"))
         self.check_zup.setChecked(cfg.getboolean("anim", "zup"))
+        self.init_clips_jsonfile()
 
 ###############################################################################################
 class w_model(QtGui.QWidget):
Add a comment to this file

src/h3dimport-gui/img/glyphicons_207_remove_2.png

Added
New image
Add a comment to this file

src/h3dimport-gui/img/glyphicons_432_plus.png

Added
New image
Add a comment to this file

src/h3dimport-gui/img/glyphicons_433_minus.png

Added
New image

src/h3dimport/anim-import.c

     char* json_data = util_readtextfile(json_filepath, mem_heap());
     if (json_data == NULL)  {
         printf(TERM_BOLDYELLOW "Warning: could not open JSON file '%s' for clips,"
-            " switching to default", json_filepath);
+            " reseting to default", json_filepath);
         *clip_cnt = 1;
         return import_defaultclip(frame_cnt);
     }
     FREE(json_data);
     if (jroot == NULL)  {
         printf(TERM_BOLDYELLOW "Warning: could not read JSON file '%s' for clips,"
-            " switching to default", json_filepath);
+            " reseting to default", json_filepath);
         *clip_cnt = 1;
         return import_defaultclip(frame_cnt);
     }
 
     /* */
-    json_t jclips = json_getitem(jroot, "clips");
+    json_t jclips = jroot;
     uint32 cnt = json_getarr_count(jclips);
     if (cnt == 0)   {
         printf(TERM_BOLDYELLOW "Warning: no clip defined in JSON file '%s',"

src/vs2010/engine.vcxproj

       </IgnoreAllDefaultLibraries>
       <AdditionalDependencies>dh_core.lib;lua.lib;mongoose.lib;libmmds.lib;%(AdditionalDependencies);PhysX3_x86.lib;PhysX3Common_x86.lib;PhysX3Extensions.lib;PhysxProfileSDK.lib;d3dcompiler.lib;dxguid.lib;d3d11.lib;dxgi.lib</AdditionalDependencies>
       <AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
+      <IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_pybind|Win32'">
       <IgnoreAllDefaultLibraries>
       </IgnoreAllDefaultLibraries>
       <AdditionalDependencies>python27.lib;dh_core.lib;lua.lib;mongoose.lib;libmmds.lib;%(AdditionalDependencies);PhysX3_x86.lib;PhysX3Common_x86.lib;PhysX3Extensions.lib;PhysxProfileSDK.lib;d3dcompiler.lib;dxguid.lib;d3d11.lib;dxgi.lib;glfw.lib;OpenGL32.lib;gl3w.lib</AdditionalDependencies>
-      <AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
     </Link>
     <PostBuildEvent>
       <Command>copy $(ProjectDir)\..\engine\pybind\dheng.py $(ProjectDir)\..\..\src\pymodules\dheng.py
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.