void VideoMetaCache::setValues(Entry& entry) { if(entry.mType == ERROR_TYPE) { DS_LOG_WARNING("Attempted to cache an invalid media (path=" << entry.mPath << ")"); return; } if(entry.mDuration < 0.0f) { DS_LOG_WARNING("Attempted to cache media with no duration (path=" << entry.mPath << ")"); return; } if(entry.mType == VIDEO_TYPE && (entry.mWidth < 1 || entry.mHeight < 1)) { DS_LOG_WARNING("Attempted to cache video with no size (path=" << entry.mPath << ", width=" << entry.mWidth << ", height=" << entry.mHeight << ")"); return; } try { const std::string db = get_db_file(mName); std::stringstream buf; buf << "SELECT id FROM video_meta WHERE path='" << entry.mPath << "'"; ds::query::Result ans; if (ds::query::Client::query(db, buf.str(), ans) && !ans.rowsAreEmpty()) { buf.str(""); buf << "UPDATE video_meta SET type='" << db_type_from_type(entry.mType) << "', width=" << entry.mWidth << ", height=" << entry.mHeight << ", duration=" << entry.mDuration << ", colorspace='" << entry.mDuration << "', videocodec='" << entry.mDuration << "', audiocodec='" << entry.mDuration << "' WHERE path='" << entry.mPath << "'"; ds::query::Client::queryWrite(db, buf.str(), ans); load(); return; } buf.str(""); buf << "INSERT INTO video_meta (type, path, width, height, duration, colorspace, videocodec, audiocodec) values ('" << db_type_from_type(entry.mType) << "', '" << entry.mPath << "', " << entry.mWidth << ", " << entry.mHeight << ", " << entry.mDuration << ", '" << entry.mColorSpace << "', '" << entry.mVideoCodec << "', '" << entry.mAudioCodec << "')"; ds::query::Client::queryWrite(db, buf.str(), ans); mEntries.push_back(entry); } catch (std::exception const&) { } //load(); }
void EngineSettings::printStartupInfo(){ if(mLoadedAnySettings){ DS_LOG_INFO(std::endl << mStartupInfo.str()); } else { DS_LOG_WARNING("No settings files loaded. Using default values."); } }
void ThreatQuery::query() { const ds::Resource::Id cms(ds::Resource::Id::CMS_TYPE, 0); std::stringstream buf; ds::query::Result r; ds::query::Result threatR; buf << "SELECT latest_threats.id, latest_threats.name FROM latest_threats ORDER BY id DESC LIMIT 10"; if (!ds::query::Client::query(cms.getDatabasePath(), buf.str(), r, ds::query::Client::INCLUDE_COLUMN_NAMES_F)) { DS_LOG_WARNING("TreatQuery error querying treats"); } if (r.rowsAreEmpty()) return; // Add the media ds::query::Result::RowIterator it(r); while (it.hasValue()) { LatestThreatModel m; m.mThreatId =it.getInt(0); m.mName = it.getWString(1); buf.str(""); buf << "SELECT country, startDate, infections FROM threat_data WHERE threatID = " << m.mThreatId; if(ds::query::Client::query(cms.getDatabasePath(), buf.str(), threatR, ds::query::Client::INCLUDE_COLUMN_NAMES_F) && !threatR.rowsAreEmpty()){ ds::query::Result::RowIterator threatIt(threatR); while(threatIt.hasValue()){ ThreatDataModel tdm; tdm.mCountry = threatIt.getWString(0); tdm.mDate = threatIt.getWString(1); tdm.mNumThreats = threatIt.getInt(2); m.mThreatData.push_back(tdm); ++threatIt; } } mLatestThreats.push_back(m); ++it; } }
void PngSequenceSprite::setImages(const std::vector<std::string>& imageFiles){ size_t i=0; for(auto it = imageFiles.begin(); it < imageFiles.end(); ++it){ bool created_new_frames = false; while ( mFrames.size() < i+1 ) { ds::ui::Image* img = new ds::ui::Image( mEngine, (*it), ds::ui::Image::IMG_CACHE_F | ds::ui::Image::IMG_PRELOAD_F ); addChild( *img ); img->hide(); mFrames.push_back( img ); created_new_frames = true; } if (!created_new_frames) mFrames[i]->setImageFile( *it, ds::ui::Image::IMG_CACHE_F | ds::ui::Image::IMG_PRELOAD_F ); i++; } mNumFrames = imageFiles.size(); // Hide all the old frames if there were previously more frames than there are now for ( i=mNumFrames; i<mFrames.size(); i++ ) mFrames[i]->hide(); if( mNumFrames == 0 ){ DS_LOG_WARNING("Png Sequence didn't load any frames. Whoops."); mPlaying = false; return; } }
const ds::cfg::Text& EngineCfg::getText(const std::string& name) const { if (name.empty()) { DS_LOG_WARNING("EngineCfg::getText() on empty name"); return mEmptyTextCfg; } if (mTextCfg.empty()) { DS_LOG_WARNING("EngineCfg::getText() on empty mTextCfg (key=" << name << ")"); return mEmptyTextCfg; } auto it = mTextCfg.find(name); if (it == mTextCfg.end()) { DS_LOG_WARNING("EngineCfg::getText() cfg does not exist: " << name); return mEmptyTextCfg; } return it->second; }
bool VideoMetaCache::getVideoInfo(Entry& entry) { MediaInfoDLL::MediaInfo media_info; if (!media_info.IsReady()) { // Indicates the DLL couldn't be loaded DS_LOG_ERROR("VideoMetaCache::getVideoInfo() MediaInfo not loaded, does dll/MediaInfo.dll exist in the app folder?"); throw std::runtime_error("VideoMetaCache::getVideoInfo() MediaInfo not loaded, does dll/MediaInfo.dll exist in the app folder?"); return false; } media_info.Open(ds::wstr_from_utf8(entry.mPath)); size_t numAudio = media_info.Count_Get(MediaInfoDLL::Stream_Audio); size_t numVideo = media_info.Count_Get(MediaInfoDLL::Stream_Video); if(numAudio < 1 && numVideo < 1){ DS_LOG_WARNING("Couldn't find any audio or video streams in " << entry.mPath); entry.mType = ERROR_TYPE; return false; } // If there's an audio channel, get it's codec if(numAudio > 0){ entry.mAudioCodec = ds::utf8_from_wstr(media_info.Get(MediaInfoDLL::Stream_Audio, 0, L"Codec", MediaInfoDLL::Info_Text)); } // No video streams, but has at least one audio stream is a AUDIO_TYPE if(numAudio > 0 && numVideo < 1){ entry.mType = AUDIO_TYPE; entry.mWidth = 0; entry.mHeight = 0; if(!ds::wstring_to_value(media_info.Get(MediaInfoDLL::Stream_Audio, 0, L"Duration", MediaInfoDLL::Info_Text), entry.mDuration)) return false; // Any number of audio streams and at least one video streams is VIDEO_TYPE } else if(numVideo > 0){ entry.mType = VIDEO_TYPE; if(!ds::wstring_to_value(media_info.Get(MediaInfoDLL::Stream_Video, 0, L"Width", MediaInfoDLL::Info_Text), entry.mWidth)) return false; if(!ds::wstring_to_value(media_info.Get(MediaInfoDLL::Stream_Video, 0, L"Height", MediaInfoDLL::Info_Text), entry.mHeight)) return false; // We don't check errors on these, cause they're not required by gstreamer to play a video, they're just nice-to-have entry.mVideoCodec = ds::utf8_from_wstr(media_info.Get(MediaInfoDLL::Stream_Video, 0, L"Codec", MediaInfoDLL::Info_Text)); entry.mColorSpace = ds::utf8_from_wstr(media_info.Get(MediaInfoDLL::Stream_Video, 0, L"Colorimetry", MediaInfoDLL::Info_Text)); ds::wstring_to_value(media_info.Get(MediaInfoDLL::Stream_Video, 0, L"Duration", MediaInfoDLL::Info_Text), entry.mDuration); } entry.mDuration /= 1000.0f; // Disabling duration check, if MediaInfo can't find it, that's ok, GStreamer can fill it in // if(entry.mDuration <= 0.0f || entry.mDuration > 360000.0f) { // 360000.0f == 100 hours. That should be enough, right? // DS_LOG_WARNING("VideoMetaCache::getVideoInfo() illegal duration (" << entry.mDuration << ") for file (" << entry.mPath << ")"); // return false; // } return true; }
void PanoramicVideo::onChildAdded(ds::ui::Sprite& child){ if (mVideoSprite){ DS_LOG_WARNING("Multiple video sprites were attempted to be registered. Gonna ignore it."); return; } else if(auto video = dynamic_cast<ds::ui::Video*>(&child)){ mVideoSprite = video; mVideoSprite->setTransparent(false); setTransparent(false); mVideoSprite->setFinalRenderToTexture(true); } }
void TouchManager::inputBegin(const int fingerId, const ci::Vec2f& touchPos){ mDiscardTouchMap[fingerId] = false; ci::Vec3f globalPoint = ci::Vec3f(touchPos, 0.0f); TouchInfo touchInfo; touchInfo.mCurrentGlobalPoint = globalPoint; touchInfo.mFingerId = fingerId; touchInfo.mStartPoint = mTouchStartPoint[touchInfo.mFingerId] = touchInfo.mCurrentGlobalPoint; mTouchPreviousPoint[fingerId] = globalPoint; touchInfo.mDeltaPoint = ci::Vec3f::zero(); // Catch a case where two "touch added" calls get processed for the same fingerID // WITHOUT a released in the middle. This would case the previous sprite to be left with an erroneous finger // So we fake remove it before adding the new one if(mFingerDispatcher[touchInfo.mFingerId]) { DS_LOG_WARNING("Double touch added on the same finger Id: " << touchInfo.mFingerId << ", removing previous sprite tracking."); touchInfo.mPickedSprite = mFingerDispatcher[touchInfo.mFingerId]; touchInfo.mPhase = TouchInfo::Removed; // fake removed touchInfo.mPassedTouch = true; // passed touch flag indicates that this info shouldn't be used to trigger buttons, etc. implementation up to each sprite mFingerDispatcher[touchInfo.mFingerId]->processTouchInfo(touchInfo); mFingerDispatcher[touchInfo.mFingerId] = nullptr; } touchInfo.mPhase = TouchInfo::Added; touchInfo.mPassedTouch = false; if(mCapture) mCapture->touchBegin(touchInfo); Sprite *currentSprite = getHit(touchInfo.mCurrentGlobalPoint); touchInfo.mPickedSprite = currentSprite; mRotationTranslator.down(touchInfo); if(mSmoothEnabled){ mTouchSmoothPoints[fingerId].clear(); mTouchSmoothPoints[fingerId].push_back(touchInfo.mCurrentGlobalPoint); } if(currentSprite) { mFingerDispatcher[touchInfo.mFingerId] = currentSprite; currentSprite->processTouchInfo(touchInfo); } if(mEngine.getTouchInfoPipeCallback()){ mEngine.getTouchInfoPipeCallback()(touchInfo); } }
static void read_text_defaults(std::unordered_map<std::string, ds::cfg::Text>& out) { ds::cfg::Settings s; try { ci::DataSourceRef ds = ci::app::App::loadResource(RES_TEXT); ci::Buffer& buf = ds->getBuffer(); if(buf.getDataSize() > 0 && buf.getDataSize() < 100000) { std::string str(static_cast<const char*>(buf.getData()), buf.getDataSize()); s.readFrom(str, true, true); } } catch(std::exception& e) { DS_LOG_WARNING("Failed to load default text settings: " << e.what()); } interpret_text_settings(s, out); }
bool parse_stylesheet(Iter first, Iter last, Rules& s) { /* * selector [, selector]* { * property: value(; property: value)*(;?) * } */ stylesheet_grammar<Iter> grammar; custom_skipper<Iter> skipper; bool r = qi::phrase_parse( first, last, grammar, skipper, s ); if (r && first == last) { return true; } else { std::string context(first, last); DS_LOG_WARNING( "Failed to parse stylesheet here: -> " << context.substr(0, 30) << "... <-" ); } return false; }
void NewsQuery::query() { const ds::Resource::Id cms(ds::Resource::Id::CMS_TYPE, 0); std::stringstream buf; ds::query::Result r; buf << "SELECT id,year,month,day,text FROM news"; if (!ds::query::Client::query(cms.getDatabasePath(), buf.str(), r, ds::query::Client::INCLUDE_COLUMN_NAMES_F)) { DS_LOG_WARNING("NewsQuery::queryType() error querying news"); } if (r.rowsAreEmpty()) return; // Add the media ds::query::Result::RowIterator it(r); while (it.hasValue()) { TickerModel m; m.mId =it.getInt(0); m.mYear = it.getInt(1); m.mMonth = it.getInt(2); m.mDay = it.getInt(3); m.mHeadline = it.getWString(4); mOutput.push_back(m); ++it; } }
bool VideoMetaCache::getValues(const std::string& videoPath, Type& outType, int& outWidth, int& outHeight, double& outDuration, std::string& outColorSpace) { for(auto it = mEntries.begin(), end = mEntries.end(); it != end; ++it) { const Entry& e(*it); if (e.mPath == videoPath){ // With updates to this system , I don't believe this fallback system is needed. // Previously, a video could be assumed to be audio if it simply couldn't be found or read. // Now, actually find audio streams, and never assume stuff like that. // Also, if a file is type==ERROR_TYPE, it isn't recorded anywhere, so the below condition can't exist #if 0 // Sort of a long story, but here's the deal: // 1. Try to load a video that doesn't exist yet, type gets saved as audio, width=0, height=0 // 2. Try to load that same video again, but now it exists. The cache will pull up audio, width & height = 0 // 3. The video will then never play until the cache is cleared manually. // 4. So to fix that, we just re-query media info every time width or height are < 1. // 5. This means audio files are queried every time. If this becomes an issue performance-wise, we can try to short-cut this. if(e.mWidth < 1 || e.mHeight < 1){ Entry newEntry = Entry(); newEntry.mPath = videoPath; if(getVideoInfo(newEntry) && newEntry.mType != ERROR_TYPE){ if(width > 0 && height > 0){ setValues(t, videoPath, width, height, duration); outType = t; outWidth = width; outHeight = height; outDuration = duration; return true; } } } #endif outType = e.mType; outWidth = e.mWidth; outHeight = e.mHeight; outDuration = e.mDuration; outColorSpace = e.mColorSpace; return true; } } // The above search for a pre-cached video info failed, so find the video info try { Entry newEntry = Entry(); newEntry.mPath = videoPath; if(!getVideoInfo(newEntry) || newEntry.mType == ERROR_TYPE){ return false; } setValues(newEntry); outType = newEntry.mType; outWidth = newEntry.mWidth; outHeight = newEntry.mHeight; outDuration = newEntry.mDuration; outColorSpace = newEntry.mColorSpace; return true; } catch (std::exception const& ex) { DS_LOG_WARNING("VideoMetaCache::getWith() error=" << ex.what()); } return true; }
void MediaPlayer::initialize(){ if(mInitialized) return; const int mediaType = mResource.getType(); if(mediaType == ds::Resource::ERROR_TYPE || mediaType == ds::Resource::FONT_TYPE){ // this is not a useful warning message in the very common case of setting the size of a MediaPlayer before loading the media // GN: This is a VERY useful message if your media isn't showing up, so we'll just check for emptiness instead of no warning if(!mResource.empty()){ DS_LOG_WARNING("Whoopsies - tried to open a media player on an invalid file type. " << mResource.getAbsoluteFilePath()); } return; } // do this first to avoid recursion problems mInitialized = true; float contentWidth = 1.0f; float contentHeight = 1.0f; mContentAspectRatio = 1.0f; bool showThumbnail = true; if(mediaType == ds::Resource::IMAGE_TYPE){ int flags = 0; if(mMediaViewerSettings.mCacheImages){ flags |= Image::IMG_CACHE_F; } mPrimaryImage = new ds::ui::Image(mEngine, mResource, flags); addChildPtr(mPrimaryImage); mPrimaryImage->checkStatus(); if(mPrimaryImage->isLoaded()){ showThumbnail = false; } else { mPrimaryImage->setOpacity(0.0f); mPrimaryImage->setStatusCallback([this](ds::ui::Image::Status status){ if(status.mCode == status.STATUS_LOADED && mPrimaryImage){ mPrimaryImage->tweenOpacity(1.0f, mAnimDuration); if(mStatusCallback){ mStatusCallback(true); } } }); } mContentAspectRatio = mPrimaryImage->getWidth() / mPrimaryImage->getHeight(); contentWidth = mPrimaryImage->getWidth(); contentHeight = mPrimaryImage->getHeight(); } else if(mediaType == ds::Resource::VIDEO_TYPE){ mVideoPlayer = new VideoPlayer(mEngine, mEmbedInterface); addChildPtr(mVideoPlayer); mVideoPlayer->setErrorCallback([this](const std::string& msg){ if(mErrorCallback) mErrorCallback(msg); }); mVideoPlayer->setGoodStatusCallback([this]{ if(mStatusCallback) mStatusCallback(true); }); mVideoPlayer->setPan(mMediaViewerSettings.mVideoPanning); mVideoPlayer->setAutoSynchronize(mMediaViewerSettings.mVideoAutoSync); mVideoPlayer->setPlayableInstances(mMediaViewerSettings.mVideoPlayableInstances); mVideoPlayer->setAutoPlayFirstFrame(mMediaViewerSettings.mVideoAutoPlayFirstFrame); mVideoPlayer->setVideoLoop(mMediaViewerSettings.mVideoLoop); mVideoPlayer->setMedia(mResource.getAbsoluteFilePath()); mContentAspectRatio = mVideoPlayer->getWidth() / mVideoPlayer->getHeight(); contentWidth = mVideoPlayer->getWidth(); contentHeight = mVideoPlayer->getHeight(); } else if(mediaType == ds::Resource::VIDEO_STREAM_TYPE){ mStreamPlayer = new StreamPlayer(mEngine, mEmbedInterface); addChildPtr(mStreamPlayer); mStreamPlayer->setErrorCallback([this](const std::string& msg){ if(mErrorCallback) mErrorCallback(msg); }); mStreamPlayer->setGoodStatusCallback([this]{ if(mStatusCallback) mStatusCallback(true); }); mStreamPlayer->setResource(mResource); mContentAspectRatio = mStreamPlayer->getWidth() / mStreamPlayer->getHeight(); contentWidth = mStreamPlayer->getWidth(); contentHeight = mStreamPlayer->getHeight(); } else if(mediaType == ds::Resource::PDF_TYPE){ mPDFPlayer = new PDFPlayer(mEngine, mEmbedInterface); addChildPtr(mPDFPlayer); mPDFPlayer->setMedia(mResource.getAbsoluteFilePath()); mPDFPlayer->setErrorCallback([this](const std::string& msg){ if(mErrorCallback) mErrorCallback(msg); }); mPDFPlayer->setGoodStatusCallback([this]{ if(mStatusCallback){ mStatusCallback(true); } }); mContentAspectRatio = mPDFPlayer->getWidth() / mPDFPlayer->getHeight(); contentWidth = mPDFPlayer->getWidth(); contentHeight = mPDFPlayer->getHeight(); } else if(mediaType == ds::Resource::WEB_TYPE){ mWebPlayer = new WebPlayer(mEngine, mEmbedInterface); addChildPtr(mWebPlayer); mWebPlayer->setWebViewSize(mMediaViewerSettings.mWebDefaultSize); mWebPlayer->setKeyboardParams(mMediaViewerSettings.mWebKeyboardPanelSize, mMediaViewerSettings.mWebKeyboardKeyScale, mMediaViewerSettings.mWebAllowKeyboard); mWebPlayer->setAllowTouchToggle(mMediaViewerSettings.mWebAllowTouchToggle); mWebPlayer->setMedia(mResource.getAbsoluteFilePath()); if(mWebPlayer->getWeb()){ mWebPlayer->getWeb()->setDocumentReadyFn([this]{ if(mStatusCallback) mStatusCallback(true); }); mWebPlayer->getWeb()->setErrorCallback([this](const std::string& errorMsg){ if(mErrorCallback) mErrorCallback(errorMsg); }); } mContentAspectRatio = mWebPlayer->getWidth() / mWebPlayer->getHeight(); contentWidth = mWebPlayer->getWidth(); contentHeight = mWebPlayer->getHeight(); } else { DS_LOG_WARNING("Whoopsies - tried to open a media player on an invalid file type. " << mResource.getAbsoluteFilePath() << " " << ds::utf8_from_wstr(mResource.getTypeName())); } if(showThumbnail && (mResource.getThumbnailId() > 0 || !mResource.getThumbnailFilePath().empty())){ int flags = 0; if(mMediaViewerSettings.mCacheImages){ flags |= Image::IMG_CACHE_F; } mThumbnailImage = new ds::ui::Image(mEngine); addChildPtr(mThumbnailImage); mThumbnailImage->sendToBack(); if(mResource.getThumbnailId() > 0){ mThumbnailImage->setImageResource(mResource.getThumbnailId(), flags); } else { mThumbnailImage->setImageFile(mResource.getThumbnailFilePath(), flags); } mThumbnailImage->setOpacity(0.0f); mThumbnailImage->setStatusCallback([this](ds::ui::Image::Status status){ if(status.mCode == status.STATUS_LOADED && mThumbnailImage){ mThumbnailImage->tweenOpacity(1.0f, mAnimDuration); } }); } setSize(contentWidth, contentHeight); if(mInitializedCallback){ mInitializedCallback(); } }
void ModelMaker::run() { if(mYamlFileLocation.length() < 1){ DS_LOG_WARNING("No file specified in model maker"); return; } std::cout << "Parsing yaml file: " << mYamlFileLocation << std::endl; mYamlLoadService.mFileLocation = mYamlFileLocation; mYamlLoadService.run(); std::vector<ModelModel> models = mYamlLoadService.mOutput; if(models.empty()){ DS_LOG_WARNING("No valid models loaded in model maker."); return; } for(auto it = models.begin(); it < models.end(); ++it){ ModelModel& mm = (*it); // make the first letter of the table name uppercase std::string tableName = mm.getTableName(); if(tableName.empty()){ DS_LOG_WARNING("Model maker got a blank table!"); continue; } std::transform(tableName.begin(), tableName.begin() + 1, tableName.begin(), ::toupper); // push all the nearby getters/setters/members into stringstreams // headers std::stringstream sCustomIncludes; std::stringstream sCustomForwardDeclares; std::stringstream sHeaderGetters; std::stringstream sHeaderSetters; // imps std::stringstream sCustomImpIncludes; std::stringstream sDataMembers; std::stringstream sCustomEmptyData; std::stringstream sImpGetters; std::stringstream sImpSetters; // strings for each column std::string thisHeaderGetter; std::string thisHeaderSetter; std::string thisEmptyData; std::string thisDataMember; std::string thisImpGetter; std::string thisImpSetter; std::map<std::string, std::string> dataMemberInitializers; // make all 'resource' flagged columns into proper resources for(auto mit = mm.getResourceColumns().begin(); mit < mm.getResourceColumns().end(); ++mit){ for(auto cit = mm.getColumns().begin(); cit < mm.getColumns().end(); ++cit){ // if this column is the resource one, set it's type to resource and move on if((*cit).getColumnName() == (*mit) && ((*cit).getType() == ModelColumn::Integer || (*cit).getType() == ModelColumn::UnsignedInt)) { ModelColumn* mc = const_cast<ModelColumn*>(&(*cit)); if(mc){ mc->setType(ModelColumn::Resource); } break; } } } // add special columns for all relations for(auto rit = mm.getRelations().begin(); rit < mm.getRelations().end(); ++rit){ const ModelRelation& mr = (*rit); if(mr.getType() == ModelRelation::Invalid) continue; // create the class name out of the foreign table name, e.g. StoryRef std::string foreignTable = mr.getForeignKeyTable(); std::transform(foreignTable.begin(), foreignTable.begin() + 1, foreignTable.begin(), ::toupper); std::stringstream foreignClass; foreignClass << foreignTable << "Ref"; // create the empty data name from the class name. e.g. EMPTY_STORY or EMPTY_STORY_ELEMENT_VECTOR std::string foreignEmptyType = foreignClass.str(); std::transform(foreignEmptyType.begin(), foreignEmptyType.end(), foreignEmptyType.begin(), ::toupper); std::stringstream foreignEmptyTypeFull; foreignEmptyTypeFull << foreignEmptyType; std::stringstream foreignDataType; if(mr.getType() == ModelRelation::Many){ foreignEmptyTypeFull << "_VECTOR"; foreignDataType << "std::vector<" << foreignClass.str() << ">"; // the 'many' types need to have a header include sCustomIncludes << "#include \"" << getFileName(mr.getForeignKeyTable(), true) << "\"" << std::endl; } else { foreignDataType << foreignClass.str(); // single types need to be forward declared to avoid circular refs sCustomForwardDeclares << "class " << foreignClass.str() << ";" << std::endl; sCustomImpIncludes << "#include \"" << getFileName(mr.getForeignKeyTable(), true) << "\"" << std::endl; } ModelColumn mc; mc.setColumnName(foreignClass.str()); mc.setType(ModelColumn::Custom); mc.setCustomDataType(foreignDataType.str()); mc.setCustomEmptyDataName(foreignEmptyTypeFull.str()); mm.addColumn(mc); } // add the getters, setters, empty data and data members for each column to the stringstreams for(auto cit = mm.getColumns().begin(); cit < mm.getColumns().end(); ++cit){ thisHeaderGetter = headerGetter; thisHeaderSetter = headerSetter; thisEmptyData = ""; thisDataMember = dataMember; thisImpGetter = impGetter; thisImpSetter = impSetter; std::string dataType = ""; const ModelColumn& mc = (*cit); // invalid columns get tossed if(mc.getType() == ModelColumn::Invalid){ continue; // if it's an int, check for unsigned int too } else if(mc.getType() == ModelColumn::Integer || mc.getType() == ModelColumn::UnsignedInt){ if(mc.getIsUnsigned()){ dataType = uintDataType; thisEmptyData = "UINT"; } else { dataType = intDataType; thisEmptyData = "INT"; } } else if(mc.getType() == ModelColumn::Float){ dataType = floatDataType; thisEmptyData = "FLOAT"; } else if(mc.getType() == ModelColumn::String){ dataType = stringDataType; thisEmptyData = "WSTRING"; } else if(mc.getType() == ModelColumn::Resource){ dataType = resourceDataType; thisEmptyData = "RESOURCE"; } else if(mc.getType() == ModelColumn::Custom){ dataType = mc.getCustomDataType(); thisEmptyData = mc.getCustomEmptyDataName(); sCustomEmptyData << "const " << mc.getCustomDataType() << " EMPTY_" << mc.getCustomEmptyDataName() << ";" << std::endl; } std::string columnName = mc.getColumnName(); std::transform(columnName.begin(), columnName.begin() + 1, columnName.begin(), ::toupper); dataMemberInitializers[columnName] = thisEmptyData; thisImpGetter = replaceAllString(thisImpGetter, "EMPTYDATATYPE", thisEmptyData); thisHeaderGetter = replaceAllString(thisHeaderGetter, "DATA_TYPE", dataType); thisHeaderSetter = replaceAllString(thisHeaderSetter, "DATA_TYPE", dataType); thisDataMember = replaceAllString(thisDataMember, "DATA_TYPE", dataType); thisImpGetter = replaceAllString(thisImpGetter, "DATA_TYPE", dataType); thisImpSetter = replaceAllString(thisImpSetter, "DATA_TYPE", dataType); sHeaderGetters << replaceAllString(thisHeaderGetter, "ColumnName", columnName) << std::endl; sHeaderSetters << replaceAllString(thisHeaderSetter, "ColumnName", columnName) << std::endl; sDataMembers << replaceAllString(thisDataMember, "ColumnName", columnName) << std::endl; sImpGetters << replaceAllString(thisImpGetter, "ColumnName", columnName) << std::endl; sImpSetters << replaceAllString(thisImpSetter, "ColumnName", columnName) << std::endl; } // add initializers to empty data when Data() is constructed std::stringstream memberInitializers; bool firstInitializer = true; for(auto it = dataMemberInitializers.begin(); it != dataMemberInitializers.end(); ++it){ if(firstInitializer){ memberInitializers << "\t: m"; firstInitializer = false; } else { memberInitializers << "\t, m"; } memberInitializers << it->first << "(EMPTY_" << it->second << ")\n"; } // add all the stringstreams to the header and put in the table name / model name std::string header = baseHeader; header = replaceAllString(header, "FORWARD_DECLARES", sCustomForwardDeclares.str()); header = replaceAllString(header, "CUSTOM_INCLUDES", sCustomIncludes.str()); header = replaceAllString(header, "COLUMN_GETTERS", sHeaderGetters.str()); header = replaceAllString(header, "COLUMN_SETTERS", sHeaderSetters.str()); header = replaceAllString(header, "TableName", tableName); //std::cout << std::endl << std::endl << header << std::endl << std::endl; std::string imp = baseCpp; imp = replaceAllString(imp, "CUSTOM_INCLUDES", sCustomImpIncludes.str()); imp = replaceAllString(imp, "CUSTOM_EMPTY_DATA", sCustomEmptyData.str()); imp = replaceAllString(imp, "INITIALIZE_DATA_MEMBERS", memberInitializers.str()); imp = replaceAllString(imp, "DATA_MEMBERS", sDataMembers.str()); imp = replaceAllString(imp, "IMP_GETTERS", sImpGetters.str()); imp = replaceAllString(imp, "IMP_SETTERS", sImpSetters.str()); imp = replaceAllString(imp, "TableName", tableName); // std::cout << std::endl << std::endl << imp << std::endl << std::endl; // write out the header and implementation std::stringstream filename; filename << "%APP%/generated/" << getFileName(mm.getTableName(), true); std::cout << "Writing header to: " << filename.str() << std::endl; std::ofstream headerWriter; headerWriter.open(ds::Environment::expand(filename.str())); headerWriter << header; headerWriter.close(); filename.str(""); filename << "%APP%/generated/" << getFileName(mm.getTableName(), false); std::cout << "Writing implementation to: " << filename.str() << std::endl; std::ofstream impWriter; impWriter.open(ds::Environment::expand(filename.str())); impWriter << imp; impWriter.close(); } }
void ScrollList::assignItems(){ if(!mScrollArea || !mScrollableHolder) return; float y = mScrollArea->getScrollerPosition().y; float x = mScrollArea->getScrollerPosition().x; float scrollHeight = mScrollArea->getHeight(); float scrollWidth = mScrollArea->getWidth(); std::vector<int> needsSprite; // Look through all the placeholdser and find all the items that should be onscreen // push the offscreen sprites into the reserve vector for(auto it = mItemPlaceHolders.begin(), it2 = mItemPlaceHolders.end(); it != it2; ++it){ float itemY = y + it->mY; float itemX = x + it->mX; if((mVerticalScrolling && ((itemY + mIncrementAmount > 0.0f) && (itemY < scrollHeight))) || (!mVerticalScrolling && ((itemX + mIncrementAmount > 0.0f) && (itemX < scrollWidth))) ){ if(it->mAssociatedSprite){ it->mAssociatedSprite->setPosition(it->mX, it->mY); } else { needsSprite.push_back(it - mItemPlaceHolders.begin()); } } else { if(it->mAssociatedSprite){ mReserveItems.push_back(it->mAssociatedSprite); } it->mAssociatedSprite = nullptr; } } // give all the placeholders that need a sprite for(auto it = needsSprite.begin(), it2 = needsSprite.end(); it != it2; ++it){ ds::ui::Sprite* sprite = nullptr; if(!mReserveItems.empty()){ sprite = mReserveItems.back(); mReserveItems.pop_back(); } else { if(mCreateItemCallback) sprite = mCreateItemCallback(); if(sprite){ sprite->setProcessTouchCallback([this](ds::ui::Sprite* sp, const ds::ui::TouchInfo& ti){ handleItemTouchInfo(sp, ti); }); sprite->setTapCallback([this, sprite](ds::ui::Sprite* bs, const ci::Vec3f cent){ Poco::Timestamp::TimeVal nowwwy = Poco::Timestamp().epochMicroseconds(); float timeDif = (float)(nowwwy - mLastUpdateTime) / 1000000.0f; if(timeDif < 0.2f){ //DS_LOG_INFO("Too soon since the last touch to tap this list!"); return; } if(mItemTappedCallback) mItemTappedCallback(sprite, cent); }); mScrollableHolder->addChildPtr(sprite); } else { DS_LOG_WARNING("Didn't create a sprite for scroll list! Use the callback and make sprites when we need them!!"); } } auto &placeHolder = mItemPlaceHolders[*it]; if(sprite){ if(mSetDataCallback) mSetDataCallback(sprite, placeHolder.mDbId); sprite->setPosition(placeHolder.mX, placeHolder.mY); sprite->show(); placeHolder.mAssociatedSprite = sprite; } } // hide any extras for(auto it = mReserveItems.begin(), it2 = mReserveItems.end(); it != it2; ++it){ auto sprite = *it; sprite->hide(); } }