├── .gitignore ├── CONTRIBUTING.md ├── Config └── FilterPlugin.ini ├── Content ├── Blueprints │ ├── ExampleActor.uasset │ ├── ExampleUI.uasset │ └── Interface │ │ ├── StomtUILayerEnum.uasset │ │ └── StomtWidgetBP.uasset ├── Maps │ └── StomtExampleMap.umap ├── Materials │ └── IconMaskMaterial.uasset ├── Sprites │ ├── Circle-black.png │ ├── Circle-black.uasset │ ├── Circle-black64x64.png │ ├── Circle-black64x64.uasset │ ├── Circle.png │ ├── Circle.uasset │ ├── LoginButton.png │ ├── LoginButton.uasset │ ├── LoginButtonClean.png │ ├── LoginButtonClean.uasset │ ├── Stomt_Logo+Wordmark_Master_RGB.png │ ├── Stomt_Logo+Wordmark_Master_RGB.uasset │ ├── WidgetForm.png │ ├── WidgetForm.uasset │ ├── WidgetFormHighRes.png │ ├── WidgetFormHighRes.uasset │ ├── WidgetFormHighRes15.png │ ├── WidgetFormHighRes15.uasset │ ├── WidgetFormHighRes30_.uasset │ ├── WidgetFormHighRes30pc.png │ ├── back-arrow-circular-symbol.png │ ├── back-arrow-circular-symbol.uasset │ ├── call-arrow-short.png │ ├── call-arrow-short.uasset │ ├── circle-32.png │ ├── circle-32.uasset │ ├── form_background.png │ ├── form_background.uasset │ ├── icon_back_gray.png │ ├── icon_back_gray.uasset │ ├── icon_image_gray.png │ ├── icon_image_gray.uasset │ ├── icon_plus-gray.png │ ├── icon_plus-gray.uasset │ ├── icon_refresh_gray.png │ ├── icon_refresh_gray.uasset │ ├── icon_refresh_white.png │ ├── icon_refresh_white.uasset │ ├── like.png │ ├── like.uasset │ ├── loading.png │ ├── loading.uasset │ ├── maxresdefault.jpg │ ├── maxresdefault.uasset │ ├── plus_disabled.png │ ├── plus_disabled.uasset │ ├── plus_enabled.png │ ├── plus_enabled.uasset │ ├── rect.png │ ├── rect.uasset │ ├── sprite150++128.png │ ├── sprite150++128.uasset │ ├── sprite150++256.png │ ├── sprite150++256.uasset │ ├── sprite150++64-greyborder.png │ ├── sprite150++64-greyborder.uasset │ ├── sprite150++64.png │ ├── sprite150++64.uasset │ ├── sprite150-border.PNG │ ├── sprite150-border.uasset │ ├── sprite150-border1024.PNG │ ├── sprite150-border1024.uasset │ ├── sprite150.PNG │ ├── sprite150.uasset │ ├── spriteCircle.PNG │ ├── spriteCircle.uasset │ ├── spriteMagicWhite.uasset │ ├── stomt-icon.png │ ├── stomt-icon.uasset │ ├── submit_enabled.png │ ├── submit_enabled.uasset │ ├── target_icon_mask.png │ ├── target_icon_mask.uasset │ ├── wish-border.png │ └── wish-border.uasset └── ThirdParty │ └── Fonts │ ├── IndieFlower.uasset │ ├── IndieFlower_Font.uasset │ ├── Lato-Bold.uasset │ ├── Lato-Bold_Font.uasset │ ├── Lato-Light.uasset │ ├── Lato-Light_Font.uasset │ ├── Lato-Regular.uasset │ └── Lato-Regular_Font.uasset ├── DEVELOPMENT.md ├── Docs ├── Images │ ├── unreal_StomtPlugin_configure_AppID.png │ ├── unreal_StomtPlugin_enable_engine_content.png │ ├── unreal_StomtPlugin_find_widget_content.png │ └── unreal_enable_StomtPlugin.png └── OpenFontLicense.txt ├── LICENSE.md ├── README.md ├── Resources ├── Icon128.png └── languages.json ├── Source └── StomtPlugin │ ├── Private │ ├── Stomt.cpp │ ├── StomtAPI.cpp │ ├── StomtConfig.cpp │ ├── StomtJsonObject.cpp │ ├── StomtJsonValue.cpp │ ├── StomtLabel.cpp │ ├── StomtPlugin.cpp │ ├── StomtPluginWidget.cpp │ ├── StomtRestRequest.cpp │ └── StomtTrack.cpp │ ├── Public │ ├── Stomt.h │ ├── StomtAPI.h │ ├── StomtConfig.h │ ├── StomtJsonObject.h │ ├── StomtJsonValue.h │ ├── StomtLabel.h │ ├── StomtPlugin.h │ ├── StomtPluginPrivatePCH.h │ ├── StomtPluginWidget.h │ ├── StomtRestRequest.h │ └── StomtTrack.h │ └── StomtPlugin.Build.cs ├── StomtPlugin.uplugin ├── pack.sh └── scripts ├── delete_branches.sh ├── push_branches.sh └── update_branches.sh /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | *.sln 44 | *.sdf 45 | 46 | # Build results 47 | 48 | [Dd]ebug/ 49 | [Rr]elease/ 50 | x64/ 51 | build/ 52 | [Bb]in/ 53 | [Oo]bj/ 54 | 55 | # MSTest test Results 56 | [Tt]est[Rr]esult*/ 57 | [Bb]uild[Ll]og.* 58 | 59 | *_i.c 60 | *_p.c 61 | *.ilk 62 | *.meta 63 | *.obj 64 | *.pch 65 | *.pdb 66 | *.pgc 67 | *.pgd 68 | *.rsp 69 | *.sbr 70 | *.tlb 71 | *.tli 72 | *.tlh 73 | *.tmp 74 | *.tmp_proj 75 | *.log 76 | *.vspscc 77 | *.vssscc 78 | .builds 79 | *.pidb 80 | *.log 81 | *.scc 82 | 83 | # Visual C++ cache files 84 | ipch/ 85 | *.aps 86 | *.ncb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | *.ncrunch* 111 | .*crunch*.local.xml 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.Publish.xml 131 | *.pubxml 132 | 133 | # NuGet Packages Directory 134 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 135 | #packages/ 136 | 137 | # Windows Azure Build Output 138 | csx 139 | *.build.csdef 140 | 141 | # Windows Store app package directory 142 | AppPackages/ 143 | 144 | # Others 145 | sql/ 146 | *.Cache 147 | ClientBin/ 148 | [Ss]tyle[Cc]op.* 149 | ~$* 150 | *~ 151 | *.dbmdl 152 | *.[Pp]ublish.xml 153 | *.pfx 154 | *.publishsettings 155 | 156 | # RIA/Silverlight projects 157 | Generated_Code/ 158 | 159 | # Backup & report files from converting an old project file to a newer 160 | # Visual Studio version. Backup files are not needed, because we have git ;-) 161 | _UpgradeReport_Files/ 162 | Backup*/ 163 | UpgradeLog*.XML 164 | UpgradeLog*.htm 165 | 166 | # SQL Server files 167 | App_Data/*.mdf 168 | App_Data/*.ldf 169 | 170 | ############# 171 | ## Windows detritus 172 | ############# 173 | 174 | # Windows image file caches 175 | Thumbs.db 176 | ehthumbs.db 177 | 178 | # Folder config file 179 | Desktop.ini 180 | 181 | # Recycle Bin used on file shares 182 | $RECYCLE.BIN/ 183 | 184 | # Mac crap 185 | .DS_Store 186 | 187 | 188 | ############# 189 | ## Python 190 | ############# 191 | 192 | *.py[co] 193 | 194 | # Packages 195 | *.egg 196 | *.egg-info 197 | dist/ 198 | build/ 199 | eggs/ 200 | parts/ 201 | var/ 202 | sdist/ 203 | develop-eggs/ 204 | .installed.cfg 205 | 206 | # Installer logs 207 | pip-log.txt 208 | 209 | # Unit test / coverage reports 210 | .coverage 211 | .tox 212 | 213 | #Translations 214 | *.mo 215 | 216 | #Mr Developer 217 | .mr.developer.cfg 218 | 219 | # Compiled Object files 220 | *.slo 221 | *.lo 222 | *.o 223 | *.obj 224 | 225 | # Compiled Dynamic libraries 226 | *.so 227 | *.dylib 228 | *.dll 229 | 230 | # Compiled Static libraries 231 | *.lai 232 | *.la 233 | *.a 234 | *.lib 235 | 236 | # Executables 237 | *.exe 238 | *.out 239 | *.app 240 | 241 | #Unreal Engine 242 | 243 | Binaries/ 244 | DerivedDataCache/ 245 | Intermediate/ 246 | Saved/ 247 | *.sln 248 | stomt.VC.opendb 249 | .vs 250 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | ### Our Pledge 22 | 23 | In the interest of fostering an open and welcoming environment, we as 24 | contributors and maintainers pledge to making participation in our project and 25 | our community a harassment-free experience for everyone, regardless of age, body 26 | size, disability, ethnicity, gender identity and expression, level of experience, 27 | nationality, personal appearance, race, religion, or sexual identity and 28 | orientation. 29 | 30 | ### Our Standards 31 | 32 | Examples of behavior that contributes to creating a positive environment 33 | include: 34 | 35 | * Using welcoming and inclusive language 36 | * Being respectful of differing viewpoints and experiences 37 | * Gracefully accepting constructive criticism 38 | * Focusing on what is best for the community 39 | * Showing empathy towards other community members 40 | 41 | Examples of unacceptable behavior by participants include: 42 | 43 | * The use of sexualized language or imagery and unwelcome sexual attention or 44 | advances 45 | * Trolling, insulting/derogatory comments, and personal or political attacks 46 | * Public or private harassment 47 | * Publishing others' private information, such as a physical or electronic 48 | address, without explicit permission 49 | * Other conduct which could reasonably be considered inappropriate in a 50 | professional setting 51 | 52 | ### Our Responsibilities 53 | 54 | Project maintainers are responsible for clarifying the standards of acceptable 55 | behavior and are expected to take appropriate and fair corrective action in 56 | response to any instances of unacceptable behavior. 57 | 58 | Project maintainers have the right and responsibility to remove, edit, or 59 | reject comments, commits, code, wiki edits, issues, and other contributions 60 | that are not aligned to this Code of Conduct, or to ban temporarily or 61 | permanently any contributor for other behaviors that they deem inappropriate, 62 | threatening, offensive, or harmful. 63 | 64 | ### Scope 65 | 66 | This Code of Conduct applies both within project spaces and in public spaces 67 | when an individual is representing the project or its community. Examples of 68 | representing a project or community include using an official project e-mail 69 | address, posting via an official social media account, or acting as an appointed 70 | representative at an online or offline event. Representation of a project may be 71 | further defined and clarified by project maintainers. 72 | 73 | ### Enforcement 74 | 75 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 76 | reported by contacting the project team at [devs@stomt.com]. All 77 | complaints will be reviewed and investigated and will result in a response that 78 | is deemed necessary and appropriate to the circumstances. The project team is 79 | obligated to maintain confidentiality with regard to the reporter of an incident. 80 | Further details of specific enforcement policies may be posted separately. 81 | 82 | Project maintainers who do not follow or enforce the Code of Conduct in good 83 | faith may face temporary or permanent repercussions as determined by other 84 | members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /Config/FilterPlugin.ini: -------------------------------------------------------------------------------- 1 | [FilterPlugin] 2 | /Docs/... 3 | -------------------------------------------------------------------------------- /Content/Blueprints/ExampleActor.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Blueprints/ExampleActor.uasset -------------------------------------------------------------------------------- /Content/Blueprints/ExampleUI.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Blueprints/ExampleUI.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Interface/StomtUILayerEnum.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Blueprints/Interface/StomtUILayerEnum.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Interface/StomtWidgetBP.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Blueprints/Interface/StomtWidgetBP.uasset -------------------------------------------------------------------------------- /Content/Maps/StomtExampleMap.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Maps/StomtExampleMap.umap -------------------------------------------------------------------------------- /Content/Materials/IconMaskMaterial.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Materials/IconMaskMaterial.uasset -------------------------------------------------------------------------------- /Content/Sprites/Circle-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle-black.png -------------------------------------------------------------------------------- /Content/Sprites/Circle-black.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle-black.uasset -------------------------------------------------------------------------------- /Content/Sprites/Circle-black64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle-black64x64.png -------------------------------------------------------------------------------- /Content/Sprites/Circle-black64x64.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle-black64x64.uasset -------------------------------------------------------------------------------- /Content/Sprites/Circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle.png -------------------------------------------------------------------------------- /Content/Sprites/Circle.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Circle.uasset -------------------------------------------------------------------------------- /Content/Sprites/LoginButton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/LoginButton.png -------------------------------------------------------------------------------- /Content/Sprites/LoginButton.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/LoginButton.uasset -------------------------------------------------------------------------------- /Content/Sprites/LoginButtonClean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/LoginButtonClean.png -------------------------------------------------------------------------------- /Content/Sprites/LoginButtonClean.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/LoginButtonClean.uasset -------------------------------------------------------------------------------- /Content/Sprites/Stomt_Logo+Wordmark_Master_RGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Stomt_Logo+Wordmark_Master_RGB.png -------------------------------------------------------------------------------- /Content/Sprites/Stomt_Logo+Wordmark_Master_RGB.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/Stomt_Logo+Wordmark_Master_RGB.uasset -------------------------------------------------------------------------------- /Content/Sprites/WidgetForm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetForm.png -------------------------------------------------------------------------------- /Content/Sprites/WidgetForm.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetForm.uasset -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes.png -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes.uasset -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes15.png -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes15.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes15.uasset -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes30_.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes30_.uasset -------------------------------------------------------------------------------- /Content/Sprites/WidgetFormHighRes30pc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/WidgetFormHighRes30pc.png -------------------------------------------------------------------------------- /Content/Sprites/back-arrow-circular-symbol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/back-arrow-circular-symbol.png -------------------------------------------------------------------------------- /Content/Sprites/back-arrow-circular-symbol.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/back-arrow-circular-symbol.uasset -------------------------------------------------------------------------------- /Content/Sprites/call-arrow-short.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/call-arrow-short.png -------------------------------------------------------------------------------- /Content/Sprites/call-arrow-short.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/call-arrow-short.uasset -------------------------------------------------------------------------------- /Content/Sprites/circle-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/circle-32.png -------------------------------------------------------------------------------- /Content/Sprites/circle-32.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/circle-32.uasset -------------------------------------------------------------------------------- /Content/Sprites/form_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/form_background.png -------------------------------------------------------------------------------- /Content/Sprites/form_background.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/form_background.uasset -------------------------------------------------------------------------------- /Content/Sprites/icon_back_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_back_gray.png -------------------------------------------------------------------------------- /Content/Sprites/icon_back_gray.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_back_gray.uasset -------------------------------------------------------------------------------- /Content/Sprites/icon_image_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_image_gray.png -------------------------------------------------------------------------------- /Content/Sprites/icon_image_gray.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_image_gray.uasset -------------------------------------------------------------------------------- /Content/Sprites/icon_plus-gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_plus-gray.png -------------------------------------------------------------------------------- /Content/Sprites/icon_plus-gray.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_plus-gray.uasset -------------------------------------------------------------------------------- /Content/Sprites/icon_refresh_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_refresh_gray.png -------------------------------------------------------------------------------- /Content/Sprites/icon_refresh_gray.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_refresh_gray.uasset -------------------------------------------------------------------------------- /Content/Sprites/icon_refresh_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_refresh_white.png -------------------------------------------------------------------------------- /Content/Sprites/icon_refresh_white.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/icon_refresh_white.uasset -------------------------------------------------------------------------------- /Content/Sprites/like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/like.png -------------------------------------------------------------------------------- /Content/Sprites/like.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/like.uasset -------------------------------------------------------------------------------- /Content/Sprites/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/loading.png -------------------------------------------------------------------------------- /Content/Sprites/loading.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/loading.uasset -------------------------------------------------------------------------------- /Content/Sprites/maxresdefault.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/maxresdefault.jpg -------------------------------------------------------------------------------- /Content/Sprites/maxresdefault.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/maxresdefault.uasset -------------------------------------------------------------------------------- /Content/Sprites/plus_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/plus_disabled.png -------------------------------------------------------------------------------- /Content/Sprites/plus_disabled.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/plus_disabled.uasset -------------------------------------------------------------------------------- /Content/Sprites/plus_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/plus_enabled.png -------------------------------------------------------------------------------- /Content/Sprites/plus_enabled.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/plus_enabled.uasset -------------------------------------------------------------------------------- /Content/Sprites/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/rect.png -------------------------------------------------------------------------------- /Content/Sprites/rect.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/rect.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150++128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++128.png -------------------------------------------------------------------------------- /Content/Sprites/sprite150++128.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++128.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150++256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++256.png -------------------------------------------------------------------------------- /Content/Sprites/sprite150++256.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++256.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150++64-greyborder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++64-greyborder.png -------------------------------------------------------------------------------- /Content/Sprites/sprite150++64-greyborder.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++64-greyborder.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150++64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++64.png -------------------------------------------------------------------------------- /Content/Sprites/sprite150++64.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150++64.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150-border.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150-border.PNG -------------------------------------------------------------------------------- /Content/Sprites/sprite150-border.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150-border.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150-border1024.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150-border1024.PNG -------------------------------------------------------------------------------- /Content/Sprites/sprite150-border1024.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150-border1024.uasset -------------------------------------------------------------------------------- /Content/Sprites/sprite150.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150.PNG -------------------------------------------------------------------------------- /Content/Sprites/sprite150.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/sprite150.uasset -------------------------------------------------------------------------------- /Content/Sprites/spriteCircle.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/spriteCircle.PNG -------------------------------------------------------------------------------- /Content/Sprites/spriteCircle.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/spriteCircle.uasset -------------------------------------------------------------------------------- /Content/Sprites/spriteMagicWhite.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/spriteMagicWhite.uasset -------------------------------------------------------------------------------- /Content/Sprites/stomt-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/stomt-icon.png -------------------------------------------------------------------------------- /Content/Sprites/stomt-icon.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/stomt-icon.uasset -------------------------------------------------------------------------------- /Content/Sprites/submit_enabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/submit_enabled.png -------------------------------------------------------------------------------- /Content/Sprites/submit_enabled.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/submit_enabled.uasset -------------------------------------------------------------------------------- /Content/Sprites/target_icon_mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/target_icon_mask.png -------------------------------------------------------------------------------- /Content/Sprites/target_icon_mask.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/target_icon_mask.uasset -------------------------------------------------------------------------------- /Content/Sprites/wish-border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/wish-border.png -------------------------------------------------------------------------------- /Content/Sprites/wish-border.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/Sprites/wish-border.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/IndieFlower.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/IndieFlower.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/IndieFlower_Font.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/IndieFlower_Font.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Bold.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Bold.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Bold_Font.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Bold_Font.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Light.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Light.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Light_Font.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Light_Font.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Regular.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Regular.uasset -------------------------------------------------------------------------------- /Content/ThirdParty/Fonts/Lato-Regular_Font.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Content/ThirdParty/Fonts/Lato-Regular_Font.uasset -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # Development 2 | 3 | ## Branches 4 | 5 | This repository contains a branch for each Engine Version. Only perform changes in one of these branches if the changes are specific for this version. All other changes are made in the `master` - this branch uses our base version `UE/4.20`. 6 | 7 | - UE/4.16 [deprecated] 8 | - UE/4.17 [deprecated] 9 | - UE/4.18 [deprecated] 10 | - UE/4.19 [deprecated] 11 | - UE/4.20 = master 12 | - UE/4.21 = master + changed EngineVersion 13 | - UE/4.22 = master + changed EngineVersion 14 | - UE/4.23 = master + changed EngineVersion 15 | - UE/4.24 = master + changed EngineVersion 16 | - UE/4.25 = master + changed EngineVersion 17 | - UE/4.26 = master + changed EngineVersion 18 | 19 | ## Release 20 | 21 | The following scripts help to perform a release. 22 | 23 | 1. Ensure that all nessessary changes have been made in the `master` branch. 24 | 25 | * Increase Version in StomtPlugin.uplugin 26 | * Update version number in StomtPlugin.uplugin 27 | * Update version number in StomtTrack.cpp line 36 28 | * commit changes "git commit -am 'bump version to X.X.X" 29 | * create tag "git tag -a vX.X.X" 30 | 31 | 2. Use `sh scripts/delete_branches.sh` to remove local changes in other branches. 32 | 33 | 3. Update the version branches by running `sh scripts/update_branches.sh`. Confirm the merges and merge commits. 34 | 35 | 4. Push the updated branches to GitHub by running `sh scripts/push_branches.sh`. 36 | 37 | 5. Now pack the version archives `sh pack.sh` and upload them for the store. 38 | -------------------------------------------------------------------------------- /Docs/Images/unreal_StomtPlugin_configure_AppID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Docs/Images/unreal_StomtPlugin_configure_AppID.png -------------------------------------------------------------------------------- /Docs/Images/unreal_StomtPlugin_enable_engine_content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Docs/Images/unreal_StomtPlugin_enable_engine_content.png -------------------------------------------------------------------------------- /Docs/Images/unreal_StomtPlugin_find_widget_content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Docs/Images/unreal_StomtPlugin_find_widget_content.png -------------------------------------------------------------------------------- /Docs/Images/unreal_enable_StomtPlugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Docs/Images/unreal_enable_StomtPlugin.png -------------------------------------------------------------------------------- /Docs/OpenFontLicense.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2014 by tyPoland Lukasz Dziedzic (team@latofonts.com) with Reserved Font Name "Lato" 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | Copyright (c) 2010, Kimberly Geswein (kimberlygeswein.com) 8 | 9 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 10 | This license is copied below, and is also available with a FAQ at: 11 | http://scripts.sil.org/OFL 12 | 13 | ----------------------------------------------------------- 14 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 15 | ----------------------------------------------------------- 16 | 17 | PREAMBLE 18 | The goals of the Open Font License (OFL) are to stimulate worldwide 19 | development of collaborative font projects, to support the font creation 20 | efforts of academic and linguistic communities, and to provide a free and 21 | open framework in which fonts may be shared and improved in partnership 22 | with others. 23 | 24 | The OFL allows the licensed fonts to be used, studied, modified and 25 | redistributed freely as long as they are not sold by themselves. The 26 | fonts, including any derivative works, can be bundled, embedded, 27 | redistributed and/or sold with any software provided that any reserved 28 | names are not used by derivative works. The fonts and derivatives, 29 | however, cannot be released under any other type of license. The 30 | requirement for fonts to remain under this license does not apply 31 | to any document created using the fonts or their derivatives. 32 | 33 | DEFINITIONS 34 | "Font Software" refers to the set of files released by the Copyright 35 | Holder(s) under this license and clearly marked as such. This may 36 | include source files, build scripts and documentation. 37 | 38 | "Reserved Font Name" refers to any names specified as such after the 39 | copyright statement(s). 40 | 41 | "Original Version" refers to the collection of Font Software components as 42 | distributed by the Copyright Holder(s). 43 | 44 | "Modified Version" refers to any derivative made by adding to, deleting, 45 | or substituting -- in part or in whole -- any of the components of the 46 | Original Version, by changing formats or by porting the Font Software to a 47 | new environment. 48 | 49 | "Author" refers to any designer, engineer, programmer, technical 50 | writer or other person who contributed to the Font Software. 51 | 52 | PERMISSION & CONDITIONS 53 | Permission is hereby granted, free of charge, to any person obtaining 54 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 55 | redistribute, and sell modified and unmodified copies of the Font 56 | Software, subject to the following conditions: 57 | 58 | 1) Neither the Font Software nor any of its individual components, 59 | in Original or Modified Versions, may be sold by itself. 60 | 61 | 2) Original or Modified Versions of the Font Software may be bundled, 62 | redistributed and/or sold with any software, provided that each copy 63 | contains the above copyright notice and this license. These can be 64 | included either as stand-alone text files, human-readable headers or 65 | in the appropriate machine-readable metadata fields within text or 66 | binary files as long as those fields can be easily viewed by the user. 67 | 68 | 3) No Modified Version of the Font Software may use the Reserved Font 69 | Name(s) unless explicit written permission is granted by the corresponding 70 | Copyright Holder. This restriction only applies to the primary font name as 71 | presented to the users. 72 | 73 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 74 | Software shall not be used to promote, endorse or advertise any 75 | Modified Version, except to acknowledge the contribution(s) of the 76 | Copyright Holder(s) and the Author(s) or with their explicit written 77 | permission. 78 | 79 | 5) The Font Software, modified or unmodified, in part or in whole, 80 | must be distributed entirely under this license, and must not be 81 | distributed under any other license. The requirement for fonts to 82 | remain under this license does not apply to any document created 83 | using the Font Software. 84 | 85 | TERMINATION 86 | This license becomes null and void if any of the above conditions are 87 | not met. 88 | 89 | DISCLAIMER 90 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 91 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 92 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 93 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 94 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 95 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 96 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 97 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 98 | OTHER DEALINGS IN THE FONT SOFTWARE. 99 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 STOMT GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Collect Feedback In-Game | STOMT for Unreal Engine 4 2 | 3 | **Implementation Time: ~20 Minutes (incl. Triggers)** 4 | 5 | **Base Unreal Version: 4.20 6 | (For specific versions visit: 7 | [4.16](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.16), 8 | [4.17](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.17), 9 | [4.18](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.18), 10 | [4.19](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.19), 11 | [4.20](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.20), 12 | [4.21](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.21), 13 | [4.22](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.22), 14 | [4.23](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.23), 15 | [4.24](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.24), 16 | [4.25](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.25), 17 | [4.26](https://github.com/stomt/stomt-unreal-plugin/tree/UE/4.26) 18 | )** 19 | 20 |

21 | STOMT Unreal Engine feedback integration 22 |

23 | 24 | This SDK allows the easy integration of the feedback solution [www.stomt.com](https://www.stomt.com/) in your Unreal apps and games. 25 | 26 | 27 | ## Use-Cases 28 | 29 | Example Games that use our integrations: 30 | 31 | * [Empires of the Undergrowth](https://www.stomt.com/empires-of-the-undergrowth) 32 | * [All Walls Must Fall](https://www.stomt.com/AWMF) 33 | * [Pantropy](https://www.stomt.com/pantropy) 34 | 35 | 36 | ## Installation 37 | 38 | ### Installation via Marketplace (recommended) 39 | 40 | 1. [Download](com.epicgames.launcher://ue/marketplace/content/7980672d57664bb5a567ff39f5106af6) the Plugin via the [Unreal Engine Marketplace](https://www.unrealengine.com/marketplace/stomt-collect-feedback-community-building) 41 | 42 | 2. Enable StomtPlugin in your Plugins Window (in Unreal Editor: `Edit -> Plugins -> Installed -> Widgets -> StomtPlugin`) 43 | 44 | Enable StomtPlugin in Unreal Editor 45 | 46 | 3. Enable "Show Engine Content" and "Show Plugin Content" in your Content Browser 47 | 48 | Unhide the Engine Content in Unreal Editor 49 | 50 | 4. Find StomtPlugin Content 51 | 52 | Discover StomtPlugins Conent 53 | 54 | 5. Place the `ExampleActor` in your scene. 55 | 56 | 6. Click play to run the game and show the feedback widget by pressing `E`. 57 | 58 | _You should now see the feedback form window in your game. Try to toggle "I wish"/"I like" and send a test stomt to "My Game" (The default test target). Then continue with [Configuration](#configuration)._ 59 | 60 | ### Manual Installation 61 | 62 | _If you use an older Unreal Engine version please check out the [`UE/[version]` branch](https://github.com/stomt/stomt-unreal-plugin/branches)._ 63 | 64 | 1. Clone or download this repository into your projects `Plugins` directory. 65 | 66 | 1.2. **If you do not use C++ code in project:** use the `Add New` button in the editor and add a blank C++ class to your project. 67 | [Guide](https://docs.unrealengine.com/latest/INT/Programming/QuickStart/2/index.html) 68 | 69 | 2. Add the StomtPlugin to your projects `PublicDependencyModuleNames` in the projects `build.cs`. `/Source/[YourProjectName]/[YourProjectName].Build.cs`: 70 | ```c++ 71 | PublicDependencyModuleNames.AddRange(new string[] { "StomtPlugin" }); // Add "StomtPlugin" String 72 | ``` 73 | 74 | 3. Restart Unreal Editor, open your project and enable the plugin. `Edit -> Plugins -> Widgets -> StomtPlugin` 75 | 76 | 4. Check `Show Plugin Content` and `Show Engine Content` in the bottom right corner of your editor (view options). 77 | 78 | Events 79 | 80 | 5. Place the `ExampleActor` in your scene. 81 | 82 | 6. Click play to run the game and show the feedback widget by pressing `E`. 83 | 84 | _You should now see the feedback form window in your game. Try to toggle "I wish"/"I like" and send a test stomt to "My Game" (The default test target). Then continue with [Configuration](#configuration)._ 85 | 86 | 87 | ## Configuration 88 | 89 | 1. Create a page for your game on [www.stomt.com](https://www.stomt.com/signup/game). 90 | 91 | 2. Create an [App Id](https://www.stomt.com/integrate) for Unreal. 92 | 93 | 3. Enter the `App Id` into the `ExampleActor` Blueprint: 94 | 95 | Unhide the Engine Content in Unreal Editor 96 | 97 | **You can disable the screenshot and log-upload functionality** 98 | 99 | STOMT Plugin configuraton 100 | 101 | 4. Add the `StomtWidgetBP` to the viewport via script (`ExampleActor`) or in your main HUD (`ExampleUI`) as widget. 102 | 103 | 104 | ## Form Triggers 105 | 106 | The widget can be opened and closed whenever you want by using our trigger functions. 107 | 108 | That allows you to: 109 | * Put a button into the main menu [(Example)](https://imgur.com/5SoQzfj) 110 | * Put a button into the HUD [(Example)](https://imgur.com/t9wPpJj) 111 | * Only show the button to certain players (e.g. power users) 112 | * Trigger the form after certain events 113 | 114 | **Define a hotkey:** 115 | 116 | STOMT Plugin Form Triggers 117 | 118 | 119 | ## Event-Callbacks 120 | 121 | The STOMT Widget supports a variety of callback events. 122 | 123 | Events 124 | 125 | ## In-Game Labeling 126 | 127 | Labels will help you track down user issues. 128 | Append labels, as for example your game-version or the player position/level. You can either hardcode them in the Unity Inspector or use a script to add them in a flexible way based on the information you have. 129 | 130 |

131 | Events 132 |

133 | 134 | **Easily add an array of labels** 135 | 136 | Events 137 | 138 | ## Issues 139 | 140 | Don't hesitate to [contact](https://www.stomt.com/stomt-unreal-engine-plugin) us if you have any issues or need help. 141 | 142 | ## Versioning 143 | 144 | We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/stomt/stomt-unreal-plugin/tags). 145 | 146 | ## Contribution 147 | 148 | We would love to see you contributing to this project. Please read [CONTRIBUTING.md](https://github.com/stomt/stomt-unreal-plugin/blob/master/CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 149 | 150 | Visit the [project on STOMT](https://www.stomt.com/stomt-unreal-plugin) to support with your ideas, wishes and feedback. 151 | 152 | ## Authors 153 | 154 | [Daniel Schukies](https://github.com/daniel-schukies) | [Follow Daniel Schukies on STOMT](https://www.stomt.com/danielschukies) 155 | 156 | See also the list of [contributors](https://github.com/stomt/stomt-unreal-engine-plugin/contributors) who participated in this project. 157 | 158 | ## More about stomt 159 | 160 | *Regularly communicate your page on social channels and checkout our [Website-Widget](https://www.stomt.com/dev/js-sdk) for your websites to collect feedback from anywhere.* 161 | 162 | * On the web [www.stomt.com](https://www.stomt.com) 163 | * [STOMT for iOS](http://stomt.co/ios) 164 | * [STOMT for Android](http://stomt.co/android) 165 | * [STOMT for Unity](http://stomt.co/unity) 166 | * [STOMT for Websites](http://stomt.co/web) 167 | * [STOMT for Wordpress](http://stomt.co/wordpress) 168 | * [STOMT for Drupal](http://stomt.co/drupal) 169 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Resources/Icon128.png -------------------------------------------------------------------------------- /Resources/languages.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": 3 | { 4 | "de": 5 | { 6 | "SDK_STOMT_WISH_BUBBLE": "Ich wünschte", 7 | "SDK_STOMT_LIKE_BUBBLE": "Ich mag", 8 | "SDK_STOMT_DEFAULT_TEXT_WISH": "würde", 9 | "SDK_STOMT_DEFAULT_TEXT_LIKE": "weil", 10 | "SDK_STOMT_PLACEHOLDER": "...bitte beende diesen Satz", 11 | "SDK_STOMT_ERROR_MORE_TEXT": "Bitte schreibe etwas mehr.", 12 | "SDK_STOMT_ERROR_LESS_TEXT": "Nutze nur {0} Zeichen.", 13 | "SDK_STOMT_SCREENSHOT": "Screenshot", 14 | 15 | "SDK_HEADER_TARGET_STOMTS": "STOMTS", 16 | "SDK_HEADER_YOUR_STOMTS": "DEINE", 17 | 18 | "SDK_SUBSCRIBE_GET_NOTIFIED": "Abonniere STOMT um über Antworten auf Deinen Wunsch informiert zu werden.", 19 | "SDK_SUBSCRIBE_TOGGLE_EMAIL": "E-Mail", 20 | "SDK_SUBSCRIBE_TOGGLE_PHONE": "SMS", 21 | "SDK_SUBSCRIBE_EMAIL_QUESTION": "Wie lautet deine E-Mail-Adresse?", 22 | "SDK_SUBSCRIBE_PHONE_QUESTION": "Wie lautet deine Telefonnummer?", 23 | "SDK_SUBSCRIBE_PHONE_PLACEHOLDER" : "+49 152 03959902", 24 | "SDK_SUBSCRIBE_EMAIL_PLACEHOLDER" : "deine@email.com", 25 | "SDK_SUBSCRIBE_DEFAULT_PLACEHOLDER" : "Wir senden dir keine Spam Nachrichten", 26 | "SDK_SUBSCRIBE_VALID_EMAIL" : "E-Mail-Adresse ist gültig, fantastisch!", 27 | "SDK_SUBSCRIBE_NO_VALID_EMAIL" : "Bitte gebe eine gültige Adresse ein.", 28 | "SDK_SUBSCRIBE_SKIP": "Überspringen", 29 | 30 | "SDK_SUCCESS_THANK_YOU": "DANKE!", 31 | "SDK_SUCCESS_FIND_ALL_STOMTS": "Super, finde mehr Wünsche auf", 32 | "SDK_SUCCESS_FIND_YOUR_STOMTS": "Finde deine stomts", 33 | "SDK_SUCCESS_CREATE_NEW_WISH": "Wünsch dir noch was", 34 | 35 | "SDK_NETWORK_NOT_CONNECTED": "Verbindung zu STOMT unterbrochen", 36 | "SDK_NETWORK_NO_INTERNET": "Keine Internetverbindung", 37 | "SDK_NETWORK_RECONNECT": "Wiederverbinden", 38 | 39 | "SDK_LOGIN_ACCOUNT_WRONG": "Account Name stimmt nicht.", 40 | "SDK_LOGIN_PASSWORD_WRONG": "Passwort stimmt nicht.", 41 | "SDK_LOGIN_PASSWORD": "Passwort", 42 | "SDK_LOGIN": "Login", 43 | "SDK_LOGIN_SIGNUP": "Anmelden", 44 | "SDK_LOGIN_LOGOUT": "Ausloggen", 45 | "SDK_LOGIN_FORGOT_PW": "Passwort vergessen?", 46 | "SDK_LOGIN_SUCCESS": "Du bist eingeloggt!", 47 | "SDK_LOGIN_WENT_WRONG": "Ups, da lief was schief.", 48 | 49 | "SDK_ADD_DETAILS": "Mehr Text", 50 | 51 | "SDK_TERMS_LOGS_OPT_IN": "Dürfen wir Log-Dateien mitsenden?", 52 | "SDK_TERMS_LOGS_OPT_IN_DIS": "Nein, bitte nicht.", 53 | "SDK_TERMS_LOGS_OPT_OUT": "Wir werden Log-Dateien anhängen.", 54 | "SDK_TERMS_LOGS_OPT_OUT_DIS": "Keine Log-Dateien anhängen." 55 | }, 56 | "en": 57 | { 58 | "SDK_STOMT_WISH_BUBBLE": "I wish", 59 | "SDK_STOMT_LIKE_BUBBLE": "I like", 60 | "SDK_STOMT_DEFAULT_TEXT_WISH": "would", 61 | "SDK_STOMT_DEFAULT_TEXT_LIKE": "because", 62 | "SDK_STOMT_PLACEHOLDER": "...please finish the sentence", 63 | "SDK_STOMT_ERROR_MORE_TEXT": "Please write a bit more.", 64 | "SDK_STOMT_ERROR_LESS_TEXT": "Use only {0} characters.", 65 | "SDK_STOMT_SCREENSHOT": "Screenshot", 66 | 67 | "SDK_HEADER_TARGET_STOMTS": "STOMTS", 68 | "SDK_HEADER_YOUR_STOMTS": "YOURS", 69 | 70 | "SDK_SUBSCRIBE_GET_NOTIFIED": "Subscribe to STOMT to get notified about responses to your wish.", 71 | "SDK_SUBSCRIBE_TOGGLE_EMAIL": "E-Mail", 72 | "SDK_SUBSCRIBE_TOGGLE_PHONE": "SMS", 73 | "SDK_SUBSCRIBE_EMAIL_QUESTION": "What's your email address?", 74 | "SDK_SUBSCRIBE_PHONE_QUESTION": "What's your phone number?", 75 | "SDK_SUBSCRIBE_PHONE_PLACEHOLDER" : "+1-541-754-3010", 76 | "SDK_SUBSCRIBE_EMAIL_PLACEHOLDER" : "your@gmail.com", 77 | "SDK_SUBSCRIBE_DEFAULT_PLACEHOLDER" : "We won’t share your contact nor spam you.", 78 | "SDK_SUBSCRIBE_VALID_EMAIL" : "Email address is valid, fantastic!", 79 | "SDK_SUBSCRIBE_NO_VALID_EMAIL" : "Please type in a valid address.", 80 | "SDK_SUBSCRIBE_SKIP": "Skip", 81 | 82 | "SDK_SUCCESS_THANK_YOU": "THANK YOU!", 83 | "SDK_SUCCESS_FIND_ALL_STOMTS": "Amazing, find more wishes on", 84 | "SDK_SUCCESS_FIND_YOUR_STOMTS": "click to find your stomts here", 85 | "SDK_SUCCESS_CREATE_NEW_WISH": "Create another wish", 86 | 87 | "SDK_NETWORK_NOT_CONNECTED": "Could not connect to STOMT", 88 | "SDK_NETWORK_NO_INTERNET": "No internet connection", 89 | "SDK_NETWORK_RECONNECT": "Reconnect", 90 | 91 | "SDK_LOGIN_ACCOUNT_WRONG": "Account was incorrect.", 92 | "SDK_LOGIN_PASSWORD_WRONG": "Password was incorrect.", 93 | "SDK_LOGIN_PASSWORD": "Password", 94 | "SDK_LOGIN": "Login", 95 | "SDK_LOGIN_SIGNUP": "Signup", 96 | "SDK_LOGIN_LOGOUT": "Logout", 97 | "SDK_LOGIN_FORGOT_PW": "Forgot password?", 98 | "SDK_LOGIN_SUCCESS": "You're now logged in!", 99 | "SDK_LOGIN_WENT_WRONG": "Ups something went wrong.", 100 | 101 | "SDK_ADD_DETAILS": "More Text", 102 | 103 | "SDK_TERMS_LOGS_OPT_IN": "May we attach log files?", 104 | "SDK_TERMS_LOGS_OPT_IN_DIS": "No, please don't.", 105 | "SDK_TERMS_LOGS_OPT_OUT": "We will attach log files to your stomt.", 106 | "SDK_TERMS_LOGS_OPT_OUT_DIS": "Do not attach log files." 107 | }, 108 | "es": 109 | { 110 | "SDK_STOMT_WISH_BUBBLE": "Quiero que", 111 | "SDK_STOMT_LIKE_BUBBLE": "Me gusta", 112 | "SDK_STOMT_DEFAULT_TEXT_WISH": "haga", 113 | "SDK_STOMT_DEFAULT_TEXT_LIKE": "porque", 114 | "SDK_STOMT_PLACEHOLDER": "... por favor termine la frase", 115 | "SDK_STOMT_ERROR_MORE_TEXT": "Por favor escriba un poco más", 116 | "SDK_STOMT_SCREENSHOT": "Captura de pantalla", 117 | "SDK_HEADER_TARGET_STOMTS": "STOMTS", 118 | "SDK_HEADER_YOUR_STOMTS": "TUYOS", 119 | "SDK_SUBSCRIBE_GET_NOTIFIED": "Suscríbete a STOMT para obtener respuestas.", 120 | "SDK_SUBSCRIBE_TOGGLE_EMAIL": "Correo", 121 | "SDK_SUBSCRIBE_TOGGLE_PHONE": "SMS", 122 | "SDK_SUBSCRIBE_EMAIL_QUESTION": "¿Cuál es tu dirección de correo electrónico?", 123 | "SDK_SUBSCRIBE_PHONE_QUESTION": "¿Cuál es tu número de teléfono?", 124 | "SDK_SUBSCRIBE_PHONE_PLACEHOLDER": "+ 1-541-754-3010", 125 | "SDK_SUBSCRIBE_EMAIL_PLACEHOLDER": "your@gmail.com", 126 | "SDK_SUBSCRIBE_SKIP": "Omitir", 127 | "SDK_SUCCESS_THANK_YOU": "¡GRACIAS!", 128 | "SDK_SUCCESS_FIND_ALL_STOMTS": "Increíble, encuentra más deseos en", 129 | "SDK_SUCCESS_FIND_YOUR_STOMTS": "haga clic para encontrar sus stomts aquí", 130 | "SDK_SUCCESS_CREATE_NEW_WISH": "Crea otra petición", 131 | "SDK_NETWORK_NOT_CONNECTED": "No se pudo conectar con STOMT", 132 | "SDK_NETWORK_NO_INTERNET": "No hay conexión a Internet", 133 | "SDK_NETWORK_RECONNECT": "Reconectar", 134 | "SDK_LOGIN": "Login", 135 | "SDK_LOGIN_LOGOUT": "Logout" 136 | }, 137 | "it": 138 | { 139 | "SDK_STOMT_WISH_BUBBLE": "Vorrei che", 140 | "SDK_STOMT_LIKE_BUBBLE": "Mi piace", 141 | "SDK_STOMT_DEFAULT_TEXT_WISH": "che", 142 | "SDK_STOMT_DEFAULT_TEXT_LIKE": "perché", 143 | "SDK_STOMT_PLACEHOLDER": "... completa la frase perfavore", 144 | "SDK_STOMT_ERROR_MORE_TEXT": "Scrivi un po 'di più perfavore.", 145 | "SDK_STOMT_SCREENSHOT": "Screenshot", 146 | "SDK_HEADER_TARGET_STOMTS": "STOMTS", 147 | "SDK_HEADER_YOUR_STOMTS": "IL TUO", 148 | "SDK_SUBSCRIBE_GET_NOTIFIED": "Iscriviti a STOMT per le risposte.", 149 | "SDK_SUBSCRIBE_TOGGLE_EMAIL": "E-Mail", 150 | "SDK_SUBSCRIBE_TOGGLE_PHONE": "SMS", 151 | "SDK_SUBSCRIBE_EMAIL_QUESTION": "Qual è il tuo indirizzo e-mail?", 152 | "SDK_SUBSCRIBE_PHONE_QUESTION": "Qual è il tuo numero di telefono?", 153 | "SDK_SUBSCRIBE_PHONE_PLACEHOLDER": "+ 1-541-754-3010", 154 | "SDK_SUBSCRIBE_EMAIL_PLACEHOLDER": "latuaemail@gmail.com", 155 | "SDK_SUBSCRIBE_SKIP": "Salta", 156 | "SDK_SUCCESS_THANK_YOU": "GRAZIE!", 157 | "SDK_SUCCESS_FIND_ALL_STOMTS": "Magnifico, trova più desideri", 158 | "SDK_SUCCESS_FIND_YOUR_STOMTS": "clicca qui per trovare i tuoi stomt", 159 | "SDK_SUCCESS_CREATE_NEW_WISH": "Crea un altro desiderio", 160 | "SDK_NETWORK_NOT_CONNECTED": "Impossibile connettersi a STOMT", 161 | "SDK_NETWORK_NO_INTERNET": "Nessuna connessione internet", 162 | "SDK_NETWORK_RECONNECT": "Ricollegati", 163 | "SDK_LOGIN": "Login", 164 | "SDK_LOGIN_LOGOUT": "Logout" 165 | }, 166 | "pt": 167 | { 168 | "SDK_STOMT_WISH_BUBBLE": "Eu gostaria que", 169 | "SDK_STOMT_LIKE_BUBBLE": "Eu gosto de", 170 | "SDK_STOMT_DEFAULT_TEXT_WISH": "", 171 | "SDK_STOMT_DEFAULT_TEXT_LIKE": "porque", 172 | "SDK_STOMT_PLACEHOLDER": "... por favor termine a frase", 173 | "SDK_STOMT_ERROR_MORE_TEXT": "Escreva um pouco mais.", 174 | "SDK_STOMT_SCREENSHOT": "Captura de tela", 175 | "SDK_HEADER_TARGET_STOMTS": "STOMTS", 176 | "SDK_HEADER_YOUR_STOMTS": "SUA", 177 | "SDK_SUBSCRIBE_GET_NOTIFIED": "Assine o STOMT para respostas.", 178 | "SDK_SUBSCRIBE_TOGGLE_EMAIL": "E-Mail", 179 | "SDK_SUBSCRIBE_TOGGLE_PHONE": "SMS", 180 | "SDK_SUBSCRIBE_EMAIL_QUESTION": "Qual é o seu e-mail?", 181 | "SDK_SUBSCRIBE_PHONE_QUESTION": "Qual é o seu número de telefone?", 182 | "SDK_SUBSCRIBE_PHONE_PLACEHOLDER": "+ 1-541-754-3010", 183 | "SDK_SUBSCRIBE_EMAIL_PLACEHOLDER": "your@gmail.com", 184 | "SDK_SUBSCRIBE_SKIP": "Pular", 185 | "SDK_SUCCESS_THANK_YOU": "OBRIGADO!", 186 | "SDK_SUCCESS_FIND_ALL_STOMTS": "Incrível, encontre mais stomts sobre", 187 | "SDK_SUCCESS_FIND_YOUR_STOMTS": "Clique aqui para encontrar seus stomts", 188 | "SDK_SUCCESS_CREATE_NEW_WISH": "Criar outro stomt", 189 | "SDK_NETWORK_NOT_CONNECTED": "Não foi possível conectar-se ao STOMT", 190 | "SDK_NETWORK_NO_INTERNET": "Sem conexão à internet", 191 | "SDK_NETWORK_RECONNECT": "Reconectar", 192 | "SDK_LOGIN": "Login", 193 | "SDK_LOGIN_LOGOUT": "Logout" 194 | } 195 | } 196 | } -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/Stomt.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "Stomt.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | 7 | ////////////////////////////////////////////////////////////////////////// 8 | // Construction 9 | 10 | UStomt::UStomt() 11 | { 12 | 13 | } 14 | 15 | UStomt* UStomt::ConstructStomt(FString NewTargetId, bool bNewPositive, FString NewText, FString NewDetails) 16 | { 17 | UStomt* NewStomt = NewObject(); 18 | NewStomt->SetTargetId(NewTargetId); 19 | NewStomt->SetPositive(bNewPositive); 20 | NewStomt->SetText(NewText); 21 | NewStomt->SetDetails(NewDetails); 22 | 23 | return NewStomt; 24 | } 25 | 26 | ////////////////////////////////////////////////////////////////////////// 27 | // Data accessors 28 | 29 | void UStomt::SetTargetId(FString NewTargetId) 30 | { 31 | this->TargetId = NewTargetId; 32 | } 33 | 34 | void UStomt::SetPositive(bool bNewPositive) 35 | { 36 | this->bPositive = bNewPositive; 37 | } 38 | 39 | void UStomt::SetText(FString NewText) 40 | { 41 | this->Text = NewText; 42 | } 43 | 44 | void UStomt::SetDetails(FString NewDetails) 45 | { 46 | this->Details = NewDetails; 47 | } 48 | 49 | void UStomt::SetAnonym(bool bNewAnonym) 50 | { 51 | this->bAnonym = bNewAnonym; 52 | } 53 | 54 | void UStomt::SetServersideId(FString NewServersideId) 55 | { 56 | this->ServersideId = NewServersideId; 57 | } 58 | 59 | void UStomt::AddLabel(UStomtLabel* newLabel) 60 | { 61 | this->Labels.Add(newLabel); 62 | } 63 | void UStomt::SetLabels(TArray NewLabels) 64 | { 65 | this->Labels = NewLabels; 66 | } 67 | 68 | void UStomt::SetLabels(TArray NewLabels) 69 | { 70 | if (NewLabels.Num() <= 0) 71 | return; 72 | 73 | this->Labels.Empty(); 74 | 75 | for (int i = 0; i != NewLabels.Num(); ++i) 76 | { 77 | this->Labels.Add(UStomtLabel::ConstructLabel(NewLabels[i])); 78 | } 79 | } 80 | 81 | FString UStomt::GetTargetId() 82 | { 83 | return this->TargetId; 84 | } 85 | 86 | bool UStomt::GetPositive() 87 | { 88 | return this->bPositive; 89 | } 90 | 91 | FString UStomt::GetText() 92 | { 93 | return this->Text; 94 | } 95 | 96 | 97 | FString UStomt::GetDetails() 98 | { 99 | return this->Details; 100 | } 101 | 102 | bool UStomt::GetAnonym() 103 | { 104 | return this->bAnonym; 105 | } 106 | TArray UStomt::GetLabels() 107 | { 108 | return this->Labels; 109 | } 110 | 111 | FString UStomt::GetServersideId() 112 | { 113 | return this->ServersideId; 114 | } 115 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtAPI.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtAPI.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | #include "StomtJsonObject.h" 7 | 8 | #include "Runtime/Engine/Public/HighResScreenshot.h" 9 | #include "Runtime/Core/Public/Misc/FileHelper.h" 10 | #include "Runtime/Core/Public/Misc/Paths.h" 11 | #include "Runtime/Core/Public/GenericPlatform/GenericPlatformFile.h" 12 | #include "Runtime/Core/Public/Misc/Base64.h" 13 | #include "Runtime/Core/Public/Misc/App.h" 14 | #include "Runtime/Core/Public/Internationalization/Regex.h" 15 | 16 | ////////////////////////////////////////////////////////////////////////// 17 | // Constructors 18 | 19 | UStomtAPI* UStomtAPI::ConstructStomtAPI(FString NewAppId) 20 | { 21 | UStomtAPI* Api = NewObject(); 22 | 23 | Api->SetAppId(NewAppId); 24 | 25 | UE_LOG(StomtInit, Log, TEXT("Construct Stomt API")); 26 | UE_LOG(StomtInit, Log, TEXT("AppId: %s "), *Api->GetAppId()); 27 | UE_LOG(StomtInit, Log, TEXT("RestUrl: %s "), *Api->GetRestUrl()); 28 | 29 | Api->LoadLanguageFile(); 30 | 31 | UE_LOG(StomtInit, Log, TEXT("LangTest: %s"), *Api->GetLangText("SDK_STOMT_WISH_BUBBLE")); 32 | 33 | return Api; 34 | } 35 | 36 | UStomtAPI::UStomtAPI() 37 | { 38 | this->bLogFileWasSend = false; 39 | this->bEMailFlagWasSend = false; 40 | this->bIsImageUploadComplete = false; 41 | this->bIsLogUploadComplete = false; 42 | this->bUseImageUpload = true; 43 | this->bUseDefaultLabels = true; 44 | this->bNetworkError = false; 45 | 46 | this->DefaultScreenshotName = FString("HighresScreenshot00000.png"); 47 | this->Config = UStomtConfig::ConstructStomtConfig(); 48 | this->Track = UStomtTrack::ConstructStomtTrack(); 49 | this->SetCurrentLanguage(this->GetSystemLanguage()); 50 | } 51 | 52 | UStomtAPI::~UStomtAPI() 53 | { 54 | } 55 | 56 | 57 | ////////////////////////////////////////////////////////////////////////// 58 | // Data accessors 59 | 60 | void UStomtAPI::SetRestUrl(FString NewRestUrl) 61 | { 62 | this->RestUrl = NewRestUrl; 63 | } 64 | 65 | FString UStomtAPI::GetRestUrl() 66 | { 67 | return this->RestUrl; 68 | } 69 | 70 | void UStomtAPI::SetStomtUrl(FString NewStomtUrl) 71 | { 72 | this->StomtUrl = NewStomtUrl; 73 | } 74 | 75 | FString UStomtAPI::GetStomtUrl() 76 | { 77 | return this->StomtUrl; 78 | } 79 | 80 | void UStomtAPI::SetAppId(FString NewAppId) 81 | { 82 | if (NewAppId.Equals("Copy_your_AppId_here") || NewAppId.Equals("AKN5M7Ob0MqxKXYdE9i3IhQtF") || NewAppId.Equals("")) 83 | { 84 | this->AppId = "AKN5M7Ob0MqxKXYdE9i3IhQtF"; 85 | this->SetRestUrl("https://test.rest.stomt.com"); 86 | this->SetStomtUrl("https://test.stomt.com/"); 87 | } 88 | else 89 | { 90 | this->AppId = NewAppId; 91 | this->SetRestUrl("https://rest.stomt.com"); 92 | this->SetStomtUrl("https://www.stomt.com/"); 93 | } 94 | } 95 | 96 | FString UStomtAPI::GetAppId() 97 | { 98 | return this->AppId; 99 | } 100 | 101 | FString UStomtAPI::GetTargetName() 102 | { 103 | return this->TargetName; 104 | } 105 | 106 | void UStomtAPI::SetTargetId(FString NewTargetId) 107 | { 108 | this->TargetId = NewTargetId; 109 | } 110 | 111 | FString UStomtAPI::GetTargetId() 112 | { 113 | return this->TargetId; 114 | } 115 | 116 | void UStomtAPI::SetImageUrl(FString NewImageUrl) 117 | { 118 | this->ImageUrl = NewImageUrl; 119 | } 120 | 121 | FString UStomtAPI::GetImageUrl() 122 | { 123 | return this->ImageUrl; 124 | } 125 | 126 | void UStomtAPI::SetStomtToSend(UStomt * NewStomt) 127 | { 128 | this->StomtToSend = NewStomt; 129 | } 130 | 131 | FString UStomtAPI::GetCurrentLanguage() 132 | { 133 | return this->CurrentLanguage; 134 | } 135 | 136 | bool UStomtAPI::SetCurrentLanguage(FString Language) 137 | { 138 | if (Language.IsEmpty()) 139 | return false; 140 | 141 | this->CurrentLanguage = Language.Left(2); 142 | 143 | return true; 144 | } 145 | 146 | FString UStomtAPI::GetSystemLanguage() 147 | { 148 | return FInternationalization::Get().GetCurrentCulture()->GetName().Left(2); 149 | } 150 | 151 | bool UStomtAPI::IsConnected() 152 | { 153 | return !bNetworkError; 154 | } 155 | 156 | 157 | ////////////////////////////////////////////////////////////////////////// 158 | // Helpers: Request 159 | 160 | UStomtRestRequest* UStomtAPI::SetupNewRequest(StomtEnumRequestVerb::Type Verb) 161 | { 162 | UStomtRestRequest* Request = NewObject(); 163 | Request->OnRequestFail.AddDynamic(this, &UStomtAPI::OnARequestFailed); 164 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::ParseAccessTokenFromResponse); 165 | 166 | Request->SetVerb(Verb); 167 | Request->SetHeader(TEXT("appid"), this->GetAppId()); 168 | this->AddAccesstokenToRequest(Request); 169 | 170 | return Request; 171 | } 172 | 173 | void UStomtAPI::AddAccesstokenToRequest(UStomtRestRequest * Request) 174 | { 175 | if (!this->Config->GetAccessToken().IsEmpty()) 176 | { 177 | Request->SetHeader(TEXT("accesstoken"), this->Config->GetAccessToken()); 178 | } 179 | } 180 | 181 | void UStomtAPI::OnARequestFailed(UStomtRestRequest * Request) 182 | { 183 | this->bNetworkError = true; 184 | this->OnRequestFailed.Broadcast(Request); 185 | } 186 | 187 | void UStomtAPI::ParseAccessTokenFromResponse(UStomtRestRequest * Request) 188 | { 189 | if (!Request->GetResponseObject()->HasField(TEXT("meta"))) return; 190 | if (!Request->GetResponseObject()->HasField(TEXT("meta"))) return; 191 | if (!Request->GetResponseObject()->GetObjectField(TEXT("meta"))->HasField(TEXT("accesstoken"))) return; 192 | 193 | FString Accesstoken = Request->GetResponseObject()->GetObjectField(TEXT("meta"))->GetStringField(TEXT("accesstoken")); 194 | if (Accesstoken.Equals(this->Config->GetAccessToken())) return; 195 | 196 | this->Config->SetAccessToken(Accesstoken); 197 | this->RequestSession(); 198 | } 199 | 200 | 201 | ////////////////////////////////////////////////////////////////////////// 202 | // Requests 203 | 204 | 205 | void UStomtAPI::SendStomt(UStomt* NewStomt) 206 | { 207 | if (!this->IsConnected()) 208 | { 209 | this->Config->AddStomt(NewStomt); 210 | return; 211 | } 212 | 213 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 214 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnSendStomtRequestResponse); 215 | 216 | // Fields 217 | Request->GetRequestObject()->SetField(TEXT("target_id"), UStomtJsonValue::ConstructJsonValueString(this, NewStomt->GetTargetId())); 218 | Request->GetRequestObject()->SetField(TEXT("positive"), UStomtJsonValue::ConstructJsonValueBool(this, NewStomt->GetPositive())); 219 | Request->GetRequestObject()->SetField(TEXT("text"), UStomtJsonValue::ConstructJsonValueString(this, NewStomt->GetText())); 220 | Request->GetRequestObject()->SetField(TEXT("details"), UStomtJsonValue::ConstructJsonValueString(this, NewStomt->GetDetails())); 221 | Request->GetRequestObject()->SetField(TEXT("anonym"), UStomtJsonValue::ConstructJsonValueBool(this, NewStomt->GetAnonym())); 222 | 223 | // Labels 224 | UStomtRestJsonObject* JObjExtraData = UStomtRestJsonObject::ConstructJsonObject(this); 225 | TArray Labels = TArray(); 226 | 227 | for (int i = 0; i != NewStomt->GetLabels().Num(); ++i) 228 | { 229 | if (!NewStomt->GetLabels()[i]->GetName().IsEmpty()) 230 | { 231 | Labels.Add(UStomtJsonValue::ConstructJsonValueString(this, NewStomt->GetLabels()[i]->GetName())); 232 | } 233 | } 234 | 235 | if (this->bUseDefaultLabels) 236 | { 237 | const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY()); 238 | Labels.Add(UStomtJsonValue::ConstructJsonValueString(this, ViewportSize.ToString())); 239 | Labels.Add(UStomtJsonValue::ConstructJsonValueString(this, UGameplayStatics::GetPlatformName())); 240 | } 241 | 242 | if (Labels.Num() > 0) 243 | { 244 | JObjExtraData->SetArrayField(TEXT("labels"), Labels); 245 | Request->GetRequestObject()->SetObjectField(TEXT("extradata"), JObjExtraData); 246 | } 247 | 248 | if (this->CustomKeyValuePairs.Num() > 0) 249 | { 250 | for (int i = 0; i != this->CustomKeyValuePairs.Num(); ++i) 251 | { 252 | JObjExtraData->SetStringField(this->CustomKeyValuePairs[i][0], this->CustomKeyValuePairs[i][1]); 253 | } 254 | } 255 | 256 | // Stomt Image 257 | if (!this->ImageUploadName.IsEmpty() && this->bUseImageUpload) 258 | { 259 | Request->GetRequestObject()->SetStringField(TEXT("img_name"), this->ImageUploadName); 260 | UE_LOG(StomtNetwork, Log, TEXT("Append Image")); 261 | } 262 | else 263 | { 264 | UE_LOG(StomtNetwork, Log, TEXT("Append no Image (Don't use image upload)")); 265 | } 266 | 267 | // Error Logs 268 | if (!this->ErrorLogFileUid.IsEmpty()) 269 | { 270 | UStomtRestJsonObject* JObjFile = UStomtRestJsonObject::ConstructJsonObject(this); 271 | UStomtRestJsonObject* JObjFileContext = UStomtRestJsonObject::ConstructJsonObject(this); 272 | JObjFileContext->SetField(TEXT("file_uid"), UStomtJsonValue::ConstructJsonValueString(this, this->ErrorLogFileUid)); 273 | 274 | JObjFile->SetObjectField(TEXT("stomt"), JObjFileContext); 275 | Request->GetRequestObject()->SetObjectField(TEXT("files"), JObjFile); 276 | } 277 | 278 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/stomts"))); 279 | } 280 | 281 | void UStomtAPI::OnSendStomtRequestResponse(UStomtRestRequest * Request) 282 | { 283 | if (Request->GetResponseCode() == 200) 284 | { 285 | if (Request->GetResponseObject()->HasField(TEXT("data"))) 286 | { 287 | if (Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("id"))) 288 | { 289 | FString Id = Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetStringField(TEXT("id")); 290 | this->Track->SetStomtId(Id); 291 | this->Track->SetEventCategory("stomt"); 292 | this->Track->SetEventAction("submit"); 293 | this->SendTrack(this->Track); 294 | return; 295 | } 296 | } 297 | } 298 | 299 | UE_LOG(StomtNetwork, Warning, TEXT("Send Stomt did not work | OnSendStomtRequestResponse")); 300 | } 301 | 302 | UStomtRestRequest* UStomtAPI::SendLoginRequest(FString UserName, FString Password) 303 | { 304 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 305 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnLoginRequestResponse); 306 | 307 | Request->UseRequestLogging(false); 308 | 309 | Request->GetRequestObject()->SetStringField(TEXT("login_method"), TEXT("normal")); 310 | Request->GetRequestObject()->SetStringField(TEXT("emailusername"), UserName); 311 | Request->GetRequestObject()->SetStringField(TEXT("password"), Password); 312 | 313 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/authentication/session"))); 314 | 315 | Request->UseRequestLogging(true); 316 | 317 | return Request; 318 | } 319 | 320 | void UStomtAPI::OnLoginRequestResponse(UStomtRestRequest * Request) 321 | { 322 | if (Request->GetResponseCode() != 200) return; 323 | if (!Request->GetResponseObject()->HasField(TEXT("data"))) return; 324 | if (!Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("accesstoken"))) return; 325 | 326 | this->Config->SetSubscribed(true); 327 | this->Config->SetLoggedIn(true); 328 | 329 | this->Track->SetEventCategory("auth"); 330 | this->Track->SetEventAction("login"); 331 | this->SendTrack(this->Track); 332 | } 333 | 334 | UStomtRestRequest* UStomtAPI::RequestSession() 335 | { 336 | if (this->Config->GetAccessToken().IsEmpty()) return NULL; 337 | 338 | UStomtRestRequest* Request = SetupNewRequest(StomtEnumRequestVerb::GET); 339 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnRequestSessionResponse); 340 | Request->ProcessUrl(this->GetRestUrl().Append("/authentication/session")); 341 | 342 | return Request; 343 | } 344 | 345 | void UStomtAPI::OnRequestSessionResponse(UStomtRestRequest * Request) 346 | { 347 | if (Request->GetResponseCode() == 419) 348 | { 349 | // Forbidden: Session invalid. (Request a new access-token via login or refresh token.) 350 | UE_LOG(StomtNetwork, Warning, TEXT("Invalid accesstoken.")); 351 | Config->SetAccessToken(""); 352 | return; 353 | } 354 | 355 | if (Request->GetResponseCode() != 200) return; 356 | if (!Request->GetResponseObject()->HasField(TEXT("data"))) return; 357 | if (!Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("user"))) return; 358 | 359 | this->StomtsCreatedByUser = (int)Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetObjectField(TEXT("user"))->GetObjectField(TEXT("stats"))->GetNumberField(TEXT("amountStomtsCreated")); 360 | this->UserId = (FString)Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetObjectField(TEXT("user"))->GetStringField("id"); 361 | 362 | OnSessionRequestComplete.Broadcast(Request); 363 | UE_LOG(StomtNetwork, Log, TEXT("StomtsCreatedByUser: %d | StomtsReceivedByTarget: %d"), StomtsCreatedByUser, StomtsReceivedByTarget); 364 | } 365 | 366 | UStomtRestRequest* UStomtAPI::RequestTargetByAppId() 367 | { 368 | UStomtRestRequest* Request = SetupNewRequest(StomtEnumRequestVerb::GET); 369 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnRequestTargetResponse); 370 | Request->ProcessUrl(this->GetRestUrl().Append("/targets/")); 371 | 372 | return Request; 373 | } 374 | 375 | UStomtRestRequest* UStomtAPI::RequestTarget(FString RequestedTargetId) 376 | { 377 | UStomtRestRequest* Request = SetupNewRequest(StomtEnumRequestVerb::GET); 378 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnRequestTargetResponse); 379 | Request->ProcessUrl(this->GetRestUrl().Append("/targets/").Append(RequestedTargetId)); 380 | 381 | return Request; 382 | } 383 | 384 | void UStomtAPI::OnRequestTargetResponse(UStomtRestRequest * Request) 385 | { 386 | if (Request->GetResponseCode() != 200) return; 387 | if (!Request->GetResponseObject()->HasField(TEXT("data"))) return; 388 | if (!Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("displayname"))) return; 389 | 390 | this->TargetName = Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetStringField(TEXT("displayname")); 391 | this->TargetId = Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetStringField(TEXT("id")); 392 | this->SetImageUrl(Request->GetResponseObject() 393 | ->GetObjectField(TEXT("data")) 394 | ->GetObjectField(TEXT("images")) 395 | ->GetObjectField(TEXT("profile")) 396 | ->GetStringField(TEXT("url"))); 397 | this->StomtsReceivedByTarget = (int)Request->GetResponseObject() 398 | ->GetObjectField(TEXT("data")) 399 | ->GetObjectField(TEXT("stats")) 400 | ->GetNumberField(TEXT("amountStomtsReceived")); 401 | } 402 | 403 | void UStomtAPI::SendLogFile(FString LogFileData, FString LogFileName) 404 | { 405 | if (LogFileData.IsEmpty()) 406 | { 407 | this->bIsLogUploadComplete = true; 408 | return; 409 | } 410 | 411 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 412 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnSendLogFileResponse); 413 | 414 | FString LogJsonString = FString(TEXT("{ \"files\": { \"stomt\": [ { \"data\":\"") + FBase64::Encode(LogFileData) + TEXT("\", \"filename\" : \"") + LogFileName + TEXT("\" } ] } }")); 415 | 416 | Request->UseStaticJsonString(true); 417 | Request->SetStaticJsonString(LogJsonString); 418 | 419 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/files"))); 420 | 421 | this->bLogFileWasSend = true; 422 | } 423 | 424 | void UStomtAPI::OnSendLogFileResponse(UStomtRestRequest * Request) 425 | { 426 | // handle response 427 | this->bLogFileWasSend = false; // ???? 428 | this->bIsLogUploadComplete = true; // ???? 429 | if (Request->GetResponseObject()->HasField(TEXT("data"))) 430 | { 431 | if (Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("files"))) 432 | { 433 | this->ErrorLogFileUid = Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetObjectField(TEXT("files"))->GetObjectField(TEXT("stomt"))->GetStringField("file_uid"); 434 | UE_LOG(StomtNetwork, Log, TEXT("Log Upload complete %s"), *this->ErrorLogFileUid); 435 | } 436 | } 437 | 438 | // next step 439 | if (!this->bUseImageUpload && this->bIsImageUploadComplete) { 440 | this->SendStomt(this->StomtToSend); 441 | UE_LOG(StomtNetwork, Log, TEXT("Sent Stomt after sending log files")); 442 | } else { 443 | UE_LOG(StomtNetwork, Log, TEXT("Wait for image upload")); 444 | } 445 | } 446 | 447 | void UStomtAPI::SendImageFile(FString ImageFileDataBase64) 448 | { 449 | if (ImageFileDataBase64.IsEmpty()) 450 | { 451 | UE_LOG(StomtNetwork, Warning, TEXT("Could not send stomt image | ImageFileDataBase64 was empty")); 452 | return; 453 | } 454 | 455 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 456 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::OnSendImageFileResponse); 457 | 458 | Request->UseStaticJsonString(true); 459 | FString ImageJson = FString(TEXT("{ \"images\": { \"stomt\": [ { \"data\":\"") + ImageFileDataBase64 + TEXT("\" } ] } }")); 460 | Request->SetStaticJsonString(ImageJson); 461 | 462 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/images"))); 463 | } 464 | 465 | void UStomtAPI::OnSendImageFileResponse(UStomtRestRequest * Request) 466 | { 467 | // handle response 468 | this->bIsImageUploadComplete = true; 469 | if (Request->GetResponseObject()->HasField(TEXT("data"))) 470 | { 471 | if (Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("images"))) 472 | { 473 | this->ImageUploadName = Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetObjectField(TEXT("images"))->GetObjectField(TEXT("stomt"))->GetStringField("name"); 474 | UE_LOG(StomtNetwork, Log, TEXT("Image Upload complete %s"), *this->ImageUploadName); 475 | } 476 | } 477 | 478 | // next step 479 | if (this->bIsImageUploadComplete) { 480 | this->SendStomt(this->StomtToSend); 481 | UE_LOG(StomtNetwork, Log, TEXT("Sent Stomt after sending image files")); 482 | } else { 483 | UE_LOG(StomtNetwork, Log, TEXT("Wait for log upload")); 484 | } 485 | } 486 | 487 | void UStomtAPI::SendSubscription(FString EMail) 488 | { 489 | SendSubscription(EMail, false); 490 | } 491 | 492 | void UStomtAPI::SendSubscription(FString EMailOrNumber, bool bUseEmail) 493 | { 494 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 495 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::UStomtAPI::OnSendEMailResponse); 496 | 497 | if (bUseEmail) 498 | { 499 | Request->GetRequestObject()->SetStringField(TEXT("email"), EMailOrNumber); 500 | } 501 | else 502 | { 503 | Request->GetRequestObject()->SetStringField(TEXT("phone"), EMailOrNumber); 504 | } 505 | 506 | Request->GetRequestObject()->SetStringField(TEXT("message"), this->GetLangText("SDK_SUBSCRIBE_GET_NOTIFIED")); 507 | 508 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/authentication/subscribe"))); 509 | } 510 | 511 | void UStomtAPI::OnSendEMailResponse(UStomtRestRequest * Request) 512 | { 513 | if (Request->GetResponseCode() != 200) return; 514 | if (!Request->GetResponseObject()->HasField(TEXT("data"))) return; 515 | if (!Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("success"))) return; 516 | if (!Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetBoolField("success")) return; 517 | 518 | this->Config->SetSubscribed(true); 519 | this->Track->SetEventCategory("auth"); 520 | this->Track->SetEventAction("subscribed"); 521 | this->SendTrack(this->Track); 522 | } 523 | 524 | void UStomtAPI::SendLogoutRequest() 525 | { 526 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::DEL); 527 | Request->OnRequestComplete.AddDynamic(this, &UStomtAPI::UStomtAPI::OnSendLogoutResponse); 528 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/authentication/session"))); 529 | 530 | this->Config->SetAccessToken(TEXT("")); 531 | this->Config->SetLoggedIn(false); 532 | this->Config->SetSubscribed(false); 533 | } 534 | 535 | void UStomtAPI::OnSendLogoutResponse(UStomtRestRequest * Request) 536 | { 537 | if (Request->GetResponseCode() == 200) 538 | { 539 | if (Request->GetResponseObject()->HasField(TEXT("data"))) 540 | { 541 | if (Request->GetResponseObject()->GetObjectField(TEXT("data"))->HasField(TEXT("success"))) 542 | { 543 | if (Request->GetResponseObject()->GetObjectField(TEXT("data"))->GetBoolField("success")) 544 | { 545 | return; // logout was successful 546 | } 547 | } 548 | } 549 | } 550 | 551 | UE_LOG(StomtNetwork, Warning, TEXT("Logout failed")); 552 | } 553 | 554 | void UStomtAPI::SendTrack(UStomtTrack * NewTrack) 555 | { 556 | UStomtRestRequest* Request = this->SetupNewRequest(StomtEnumRequestVerb::POST); 557 | 558 | // Add target id 559 | NewTrack->SetTargetId(this->GetTargetId()); 560 | UStomtRestJsonObject* JObjTrack = NewTrack->GetAsJsonObject(); 561 | 562 | if (JObjTrack == NULL) 563 | { 564 | UE_LOG(StomtNetwork, Warning, TEXT("SendTrack: track was null")); 565 | return; 566 | } 567 | 568 | if (!JObjTrack->IsValidLowLevel()) 569 | { 570 | UE_LOG(StomtNetwork, Warning, TEXT("SendTrack: track not valid")); 571 | return; 572 | } 573 | 574 | Request->SetRequestObject(JObjTrack); 575 | Request->ProcessUrl(this->GetRestUrl().Append(TEXT("/tracks"))); 576 | } 577 | 578 | 579 | ////////////////////////////////////////////////////////////////////////// 580 | // Other 581 | 582 | FString UStomtAPI::ReadLogFile(FString LogFileName) 583 | { 584 | FString ErrorLog; 585 | 586 | FString LogFilePath = FPaths::ProjectLogDir() + LogFileName; 587 | FString LogFileCopyPath = FPaths::ProjectLogDir() + LogFileName + TEXT("Copy.log"); 588 | FString LogFileCopyName = LogFileName + TEXT("Copy.log"); 589 | 590 | IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); 591 | PlatformFile.BypassSecurity(true); 592 | 593 | // Copy LogFileData 594 | if (!PlatformFile.CopyFile(*LogFileCopyPath, *LogFilePath, EPlatformFileRead::AllowWrite, EPlatformFileWrite::AllowRead)) 595 | { 596 | UE_LOG(StomtFileAccess, Warning, TEXT("LogFile Copy did not work FromFile: %s | ToFile %s"), *LogFilePath, *LogFileCopyPath); 597 | return TEXT(""); 598 | } 599 | 600 | // Read LogFileCopy from Disk 601 | if (!this->ReadFile(ErrorLog, LogFileCopyName, FPaths::ProjectLogDir() )) 602 | { 603 | if (FPaths::FileExists(FPaths::ProjectLogDir() + LogFileCopyName)) 604 | { 605 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not read LogFile %s, but it exists"), *LogFileCopyName); 606 | } 607 | else 608 | { 609 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not read LogFile %s, because it does not exist"), *LogFileCopyName); 610 | } 611 | } 612 | 613 | // Delete LogFileCopy 614 | if (!PlatformFile.DeleteFile(*LogFileCopyPath)) 615 | { 616 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not delete LogFileCopy %s"), *LogFileCopyPath); 617 | } 618 | 619 | return ErrorLog; 620 | } 621 | 622 | FString UStomtAPI::ReadScreenshotAsBase64() 623 | { 624 | FString ScreenDir = FPaths::ScreenShotDir(); 625 | FString FilePath = ScreenDir + this->DefaultScreenshotName; 626 | 627 | UE_LOG(StomtLog, Log, TEXT("TakeScreenshot | FilePath: %s"), *FilePath); 628 | UE_LOG(StomtLog, Log, TEXT("Screenshot | AllocatedSize: %d"), this->ReadBinaryFile(FilePath).GetAllocatedSize()); 629 | 630 | TArray File = this->ReadBinaryFile(FilePath); 631 | 632 | //Delete Screenshot 633 | FString AbsoluteFilePath = ScreenDir + this->DefaultScreenshotName; 634 | if (!FPlatformFileManager::Get().GetPlatformFile().DeleteFile(*AbsoluteFilePath)) 635 | { 636 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not delete old screenshot File (Could Not Find Screenshot File)") ); 637 | } 638 | 639 | return FBase64::Encode(File); 640 | } 641 | 642 | void UStomtAPI::ConnectionTest() 643 | { 644 | this->RequestTargetByAppId(); 645 | } 646 | 647 | UStomtRestJsonObject* UStomtAPI::LoadLanguageFile() 648 | { 649 | FString JsonString = this->LoadLanguageFileContent(); 650 | UStomtRestJsonObject* JsonObject = UStomtRestJsonObject::ConstructJsonObject(this); 651 | if (JsonObject->DecodeJson(JsonString)) 652 | { 653 | this->Languages = JsonObject; 654 | } 655 | else 656 | { 657 | UE_LOG(StomtInit, Error, TEXT("Could not decode Language File StomtPlugin(Sub)/Resources/languages.json")); 658 | } 659 | 660 | return JsonObject; 661 | } 662 | 663 | FString UStomtAPI::LoadLanguageFileContent() 664 | { 665 | TArray PluginFolders; 666 | PluginFolders.Add(FPaths::EnginePluginsDir() + "Marketplace/"); 667 | PluginFolders.Add(FPaths::ProjectPluginsDir()); 668 | PluginFolders.Add(FPaths::ProjectPluginsDir()); 669 | PluginFolders.Add(FPaths::EnterprisePluginsDir()); 670 | 671 | TArray PluginNames; 672 | PluginNames.Add("StomtPlugin/"); 673 | PluginNames.Add("StomtPluginSub/"); 674 | PluginNames.Add("stomt-unreal-plugin/"); 675 | 676 | FString LocalFolder = "Resources/"; 677 | 678 | FString FileName = "languages.json"; 679 | 680 | FString WorkingPath = ""; 681 | 682 | for (auto& StrFolder : PluginFolders) 683 | { 684 | for (auto& StrPluginName : PluginNames) 685 | { 686 | if (FPaths::FileExists(StrFolder + StrPluginName + LocalFolder + FileName)) 687 | { 688 | WorkingPath = StrFolder + StrPluginName + LocalFolder; 689 | UE_LOG(StomtInit, Log, TEXT("Using language file in path: %s"), *WorkingPath); 690 | } 691 | } 692 | } 693 | 694 | FString JsonString = ""; 695 | 696 | if( this->ReadFile(JsonString, FileName, WorkingPath) ) 697 | { 698 | return JsonString; 699 | } 700 | 701 | if (WorkingPath.IsEmpty()) 702 | { 703 | UE_LOG(StomtInit, Warning, TEXT("Language file not found")); 704 | 705 | JsonString = "{\"data\":{\"de\": {\"SDK_STOMT_WISH_BUBBLE\": \"Ich wünschte\",\"SDK_STOMT_LIKE_BUBBLE\": \"Ich mag\",\"SDK_STOMT_DEFAULT_TEXT_WISH\": \"würde\",\"SDK_STOMT_DEFAULT_TEXT_LIKE\": \"weil\",\"SDK_STOMT_PLACEHOLDER\": \"...bitte beende diesen Satz\",\"SDK_STOMT_ERROR_MORE_TEXT\": \"Bitte schreibe etwas mehr.\",\"SDK_STOMT_ERROR_LESS_TEXT\": \"Nutze nur {0} Zeichen.\", \"SDK_STOMT_SCREENSHOT\": \"Screenshot\",\"SDK_HEADER_TARGET_STOMTS\": \"STOMTS\",\"SDK_HEADER_YOUR_STOMTS\": \"DEINE\",\"SDK_SUBSCRIBE_GET_NOTIFIED\": \"Werde benachrichtigt, wenn jemand reagiert.\",\"SDK_SUBSCRIBE_TOGGLE_EMAIL\": \"E-Mail\",\"SDK_SUBSCRIBE_TOGGLE_PHONE\": \"SMS\",\"SDK_SUBSCRIBE_EMAIL_QUESTION\": \"Wie lautet deine E-Mail-Adresse?\",\"SDK_SUBSCRIBE_PHONE_QUESTION\": \"Wie lautet deine Telefonnummer?\",\"SDK_SUBSCRIBE_PHONE_PLACEHOLDER\" : \"+49 152 03959902\",\"SDK_SUBSCRIBE_EMAIL_PLACEHOLDER\" : \"deine@email.com\",\"SDK_SUBSCRIBE_DEFAULT_PLACEHOLDER\" : \"Wir senden dir keine Spam Nachrichten\",\"SDK_SUBSCRIBE_VALID_EMAIL\" : \"E-Mail-Adresse ist gültig, fantastisch!\",\"SDK_SUBSCRIBE_NO_VALID_EMAIL\" : \"Bitte gebe eine gültige Adresse ein.\",\"SDK_SUBSCRIBE_SKIP\": \"Überspringen\",\"SDK_SUCCESS_THANK_YOU\": \"DANKE!\",\"SDK_SUCCESS_FIND_ALL_STOMTS\": \"Super, finde mehr Wünsche auf\",\"SDK_SUCCESS_FIND_YOUR_STOMTS\": \"Finde deine stomts\",\"SDK_SUCCESS_CREATE_NEW_WISH\": \"Wünsch dir noch was\",\"SDK_NETWORK_NOT_CONNECTED\": \"Verbindung zu STOMT unterbrochen\",\"SDK_NETWORK_NO_INTERNET\": \"Keine Internetverbindung\",\"SDK_NETWORK_RECONNECT\": \"Wiederverbinden\",\"SDK_LOGIN_ACCOUNT_WRONG\": \"Account Name stimmt nicht.\",\"SDK_LOGIN_PASSWORD_WRONG\": \"Passwort stimmt nicht.\",\"SDK_LOGIN_PASSWORD\": \"Passwort\",\"SDK_LOGIN\": \"Login\",\"SDK_LOGIN_SIGNUP\": \"Anmelden\",\"SDK_LOGIN_LOGOUT\": \"Ausloggen\",\"SDK_LOGIN_FORGOT_PW\": \"Passwort vergessen?\",\"SDK_LOGIN_SUCCESS\": \"Du bist eingeloggt!\",\"SDK_LOGIN_WENT_WRONG\": \"Ups, da lief was schief.\",\"SDK_ADD_DETAILS\": \"Mehr Text\",\"SDK_TERMS_LOGS_OPT_IN\": \"Dürfen wir Log-Dateien mitsenden?\",\"SDK_TERMS_LOGS_OPT_IN_DIS\": \"Nein, bitte nicht.\",\"SDK_TERMS_LOGS_OPT_OUT\": \"Wir werden Log-Dateien anhängen.\",\"SDK_TERMS_LOGS_OPT_OUT_DIS\": \"Keine Log-Dateien anhängen.\"},\"en\": {\"SDK_STOMT_WISH_BUBBLE\": \"I wish\",\"SDK_STOMT_LIKE_BUBBLE\": \"I like\",\"SDK_STOMT_DEFAULT_TEXT_WISH\": \"would\",\"SDK_STOMT_DEFAULT_TEXT_LIKE\": \"because\",\"SDK_STOMT_PLACEHOLDER\": \"...please finish the sentence\",\"SDK_STOMT_ERROR_MORE_TEXT\": \"Please write a bit more.\",\"SDK_STOMT_ERROR_LESS_TEXT\": \"Use only {0} characters.\", \"SDK_STOMT_SCREENSHOT\": \"Screenshot\",\"SDK_HEADER_TARGET_STOMTS\": \"STOMTS\",\"SDK_HEADER_YOUR_STOMTS\": \"YOURS\",\"SDK_SUBSCRIBE_GET_NOTIFIED\": \"Get notified when someone reacts.\",\"SDK_SUBSCRIBE_TOGGLE_EMAIL\": \"E-Mail\",\"SDK_SUBSCRIBE_TOGGLE_PHONE\": \"SMS\",\"SDK_SUBSCRIBE_EMAIL_QUESTION\": \"What's your email address?\",\"SDK_SUBSCRIBE_PHONE_QUESTION\": \"What's your phone number?\",\"SDK_SUBSCRIBE_PHONE_PLACEHOLDER\" : \"+1-541-754-3010\",\"SDK_SUBSCRIBE_EMAIL_PLACEHOLDER\" : \"your@gmail.com\",\"SDK_SUBSCRIBE_DEFAULT_PLACEHOLDER\" : \"We won’t share your contact nor spam you.\",\"SDK_SUBSCRIBE_VALID_EMAIL\" : \"Email address is valid, fantastic!\",\"SDK_SUBSCRIBE_NO_VALID_EMAIL\" : \"Please type in a valid address.\",\"SDK_SUBSCRIBE_SKIP\": \"Skip\",\"SDK_SUCCESS_THANK_YOU\": \"THANK YOU!\",\"SDK_SUCCESS_FIND_ALL_STOMTS\": \"Amazing, find more wishes on\",\"SDK_SUCCESS_FIND_YOUR_STOMTS\": \"click to find your stomts here\",\"SDK_SUCCESS_CREATE_NEW_WISH\": \"Create another wish\",\"SDK_NETWORK_NOT_CONNECTED\": \"Could not connect to STOMT\",\"SDK_NETWORK_NO_INTERNET\": \"No internet connection\",\"SDK_NETWORK_RECONNECT\": \"Reconnect\",\"SDK_LOGIN_ACCOUNT_WRONG\": \"Account was incorrect.\",\"SDK_LOGIN_PASSWORD_WRONG\": \"Password was incorrect.\",\"SDK_LOGIN_PASSWORD\": \"Password\",\"SDK_LOGIN\": \"Login\",\"SDK_LOGIN_SIGNUP\": \"Signup\",\"SDK_LOGIN_LOGOUT\": \"Logout\",\"SDK_LOGIN_FORGOT_PW\": \"Forgot password?\",\"SDK_LOGIN_SUCCESS\": \"You're now logged in!\",\"SDK_LOGIN_WENT_WRONG\": \"Ups something went wrong.\",\"SDK_ADD_DETAILS\": \"More Text\",\"SDK_TERMS_LOGS_OPT_IN\": \"May we attach log files?\",\"SDK_TERMS_LOGS_OPT_IN_DIS\": \"No, please don't.\",\"SDK_TERMS_LOGS_OPT_OUT\": \"We will attach log files to your stomt.\",\"SDK_TERMS_LOGS_OPT_OUT_DIS\": \"Do not attach log files.\"}}}"; 706 | return JsonString; 707 | } 708 | 709 | return JsonString; 710 | } 711 | 712 | FString UStomtAPI::GetLangText(FString Text) 713 | { 714 | if (this->CurrentLanguage.IsEmpty()) 715 | { 716 | this->CurrentLanguage = "en"; 717 | } 718 | 719 | if (this->Languages != NULL) 720 | { 721 | if (!this->Languages->HasField("data")) 722 | { 723 | return ""; 724 | } 725 | 726 | if (this->Languages->GetObjectField("data") != NULL) 727 | { 728 | if (!this->Languages->GetObjectField("data")->HasField(this->CurrentLanguage)) 729 | { 730 | UE_LOG(StomtNetwork, Warning, TEXT("Language %s not supported (does not exist in language file) falling back to english."), *this->CurrentLanguage); 731 | this->CurrentLanguage = "en"; 732 | } 733 | 734 | if (!this->Languages->GetObjectField("data")->GetObjectField(this->CurrentLanguage)->HasField(Text)) 735 | { 736 | UE_LOG(StomtNetwork, Warning, TEXT("Translation for '%s' not found in language: '%s'."), *Text, *this->CurrentLanguage); 737 | return "No Transl."; 738 | } 739 | 740 | return this->Languages->GetObjectField("data")->GetObjectField(this->CurrentLanguage)->GetStringField(Text); 741 | } 742 | } 743 | 744 | return FString(); 745 | } 746 | 747 | bool UStomtAPI::IsEmailCorrect(FString Email) 748 | { 749 | const FRegexPattern Pattern(TEXT("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")); 750 | FRegexMatcher matcher(Pattern, Email); 751 | 752 | return matcher.FindNext(); 753 | } 754 | 755 | bool UStomtAPI::DoesScreenshotFileExist() 756 | { 757 | return FPaths::FileExists(FPaths::ScreenShotDir() + this->DefaultScreenshotName); 758 | } 759 | 760 | void UStomtAPI::UseScreenshotUpload(bool bUseUpload) 761 | { 762 | this->bUseImageUpload = bUseUpload; 763 | } 764 | 765 | void UStomtAPI::AddCustomKeyValuePair(FString Key, FString Value) 766 | { 767 | TArray Pair = TArray(); 768 | Pair.Add(Key); 769 | Pair.Add(Value); 770 | 771 | CustomKeyValuePairs.Add(Pair); 772 | } 773 | 774 | void UStomtAPI::HandleOfflineStomts() 775 | { 776 | if (this->IsConnected()) 777 | { 778 | UE_LOG(StomtNetwork, Log, TEXT("Stomt API is connected.")); 779 | this->SendOfflineStomts(); 780 | } 781 | else 782 | { 783 | this->Config->AddStomt(this->StomtToSend); 784 | } 785 | } 786 | 787 | void UStomtAPI::SendOfflineStomts() 788 | { 789 | TArray Stomts = this->Config->GetStomts(); 790 | if (Stomts.Num() > 0) 791 | { 792 | UE_LOG(StomtNetwork, Log, TEXT("Start sending offline stomts: %d"), Stomts.Num()); 793 | for (UStomt* OneStomt : Stomts) 794 | { 795 | UE_LOG(StomtNetwork, Log, TEXT("Sending Offline Stomt")); 796 | this->SendStomt(OneStomt); 797 | } 798 | 799 | this->Config->ClearStomts(); 800 | } 801 | } 802 | 803 | bool UStomtAPI::WriteFile(FString TextToSave, FString FileName, FString SaveDirectory, bool bAllowOverwriting) 804 | { 805 | IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); 806 | 807 | // CreateDirectoryTree returns true if the destination 808 | // directory existed prior to call or has been created 809 | // during the call. 810 | if (PlatformFile.CreateDirectoryTree(*SaveDirectory)) 811 | { 812 | // Get absolute file path 813 | FString AbsoluteFilePath = SaveDirectory + "/" + FileName; 814 | 815 | // Allow overwriting or file doesn't already exist 816 | if (bAllowOverwriting || !FPaths::FileExists(*AbsoluteFilePath)) 817 | { 818 | //Use " FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), EFileWrite::FILEWRITE_Append);" for append 819 | return FFileHelper::SaveStringToFile(TextToSave, *AbsoluteFilePath); 820 | } 821 | else 822 | { 823 | return false; 824 | } 825 | } 826 | else 827 | { 828 | return false; 829 | } 830 | } 831 | 832 | bool UStomtAPI::ReadFile(FString& Result, FString FileName, FString SaveDirectory) 833 | { 834 | FString Path = SaveDirectory + FileName; 835 | 836 | if (!FPaths::FileExists(Path)) 837 | { 838 | UE_LOG(StomtFileAccess, Warning, TEXT("File with this path does not exist: %s "), *Path); 839 | 840 | return false; 841 | } 842 | 843 | return FFileHelper::LoadFileToString( Result, *Path); 844 | } 845 | 846 | TArray UStomtAPI::ReadBinaryFile(FString FilePath) 847 | { 848 | TArray BufferArray; 849 | FFileHelper::LoadFileToArray(BufferArray, *FilePath); 850 | 851 | return BufferArray; 852 | } 853 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtConfig.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtConfig.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | #include "StomtJsonObject.h" 7 | 8 | 9 | #include "Runtime/Core/Public/Misc/FileHelper.h" 10 | #include "Runtime/Core/Public/Misc/Paths.h" 11 | #include "Runtime/Core/Public/GenericPlatform/GenericPlatformFile.h" 12 | #include "Runtime/Core/Public/Misc/App.h" 13 | 14 | UStomtConfig* UStomtConfig::ConstructStomtConfig() 15 | { 16 | UStomtConfig* Config = NewObject(); 17 | 18 | Config->ConfigFolder = FPaths::EngineUserDir() + FString(TEXT("Saved/Config/stomt/")); 19 | UE_LOG(StomtInit, Log, TEXT("Config-Folder: %s"), *Config->ConfigFolder); 20 | 21 | Config->ConfigName = FString(TEXT("stomt.conf.json")); 22 | Config->AccessToken = FString(TEXT("")); 23 | Config->LoggedInFieldName = FString(TEXT("loggedin")); 24 | Config->SubscribedFieldName = FString(TEXT("email")); 25 | Config->AccessTokenFieldName = FString(TEXT("accesstoken")); 26 | Config->StomtsFieldName = FString(TEXT("stomts")); 27 | Config->LogUploadFieldName = FString(TEXT("acceptLogUpload")); 28 | Config->ScreenshotUploadFieldName = FString(TEXT("acceptScreenshotUpload")); 29 | 30 | Config->Load(); 31 | 32 | return Config; 33 | } 34 | 35 | UStomtConfig::UStomtConfig() 36 | { 37 | } 38 | 39 | UStomtConfig::~UStomtConfig() 40 | { 41 | } 42 | 43 | void UStomtConfig::Load() 44 | { 45 | // Use this if you experience crashes at bake process. 46 | /* #if UE_EDITOR 47 | if (!IsRunningGame()) 48 | { 49 | return; 50 | } 51 | #endif 52 | */ 53 | 54 | if (FPaths::FileExists(this->ConfigFolder + this->ConfigName)) 55 | { 56 | UStomtRestJsonObject* ConfigJsonObj = ReadStomtConfAsJson(); 57 | 58 | if (ConfigJsonObj->HasField(this->AccessTokenFieldName)) 59 | { 60 | this->AccessToken = ConfigJsonObj->GetStringField(this->AccessTokenFieldName); 61 | UE_LOG(StomtInit, Log, TEXT("AccessToken: %s"), *this->AccessToken); 62 | } 63 | 64 | if (ConfigJsonObj->HasField(this->SubscribedFieldName)) 65 | { 66 | this->bSubscribed = ConfigJsonObj->GetBoolField(this->SubscribedFieldName); 67 | UE_LOG(StomtInit, Log, TEXT("Subscribed: %s"), this->bSubscribed ? TEXT("true") : TEXT("false")); 68 | } 69 | else 70 | { 71 | this->bSubscribed = false; 72 | } 73 | 74 | if (ConfigJsonObj->HasField(this->LoggedInFieldName)) 75 | { 76 | this->bLoggedIn = ConfigJsonObj->GetBoolField(this->LoggedInFieldName); 77 | UE_LOG(StomtInit, Log, TEXT("LoggedIn: %s"), this->bLoggedIn ? TEXT("true") : TEXT("false") ); 78 | } 79 | else 80 | { 81 | this->bLoggedIn = false; 82 | } 83 | 84 | if (ConfigJsonObj->HasField(this->LogUploadFieldName)) 85 | { 86 | this->bAcceptLogUpload = ConfigJsonObj->GetBoolField(this->LogUploadFieldName); 87 | UE_LOG(StomtInit, Log, TEXT("Accept Log Upload: %s"), this->bAcceptLogUpload ? TEXT("true") : TEXT("false")); 88 | } 89 | else 90 | { 91 | this->bAcceptLogUpload = false; 92 | } 93 | 94 | if (ConfigJsonObj->HasField(this->ScreenshotUploadFieldName)) 95 | { 96 | this->bAcceptScreenshotUpload = ConfigJsonObj->GetBoolField(this->ScreenshotUploadFieldName); 97 | UE_LOG(StomtInit, Log, TEXT("Accept Screenshot Upload: %s"), this->bAcceptScreenshotUpload ? TEXT("true") : TEXT("false")); 98 | } 99 | else 100 | { 101 | this->bAcceptScreenshotUpload = false; 102 | } 103 | 104 | if (ConfigJsonObj->HasField(this->StomtsFieldName)) 105 | { 106 | this->Stomts = ConfigJsonObj->GetArrayField(this->StomtsFieldName); 107 | UE_LOG(StomtInit, Log, TEXT("Saved Offline Stomts: %d"), this->Stomts.Num()); 108 | } 109 | else 110 | { 111 | UE_LOG(StomtInit, Log, TEXT("Saved Offline Stomts: 0")); 112 | } 113 | 114 | OnConfigUpdated.Broadcast(this); 115 | } 116 | else 117 | { 118 | // Force to create config file 119 | this->bSubscribed = true; 120 | this->bLoggedIn = true; 121 | this->SetSubscribed(false); 122 | this->SetLoggedIn(false); 123 | 124 | OnConfigUpdated.Broadcast(this); 125 | } 126 | } 127 | 128 | void UStomtConfig::Delete() 129 | { 130 | this->DeleteStomtConf(); 131 | this->Load(); 132 | } 133 | 134 | FString UStomtConfig::GetAccessToken() 135 | { 136 | if (this->AccessToken.IsEmpty()) 137 | { 138 | this->AccessToken = this->ReadAccessToken(); 139 | } 140 | 141 | return this->AccessToken; 142 | } 143 | 144 | void UStomtConfig::SetAccessToken(FString NewAccessToken) 145 | { 146 | if (this->AccessToken.Equals(NewAccessToken)) return; 147 | 148 | this->AccessToken = NewAccessToken; 149 | 150 | this->SaveAccessToken(this->AccessToken); 151 | 152 | OnConfigUpdated.Broadcast(this); 153 | } 154 | 155 | bool UStomtConfig::GetSubscribed() 156 | { 157 | return this->bSubscribed; 158 | } 159 | 160 | void UStomtConfig::SetSubscribed(bool bNewSubscribed) 161 | { 162 | if (this->bSubscribed == bNewSubscribed) return; 163 | 164 | this->bSubscribed = bNewSubscribed; 165 | 166 | this->SaveFlag(this->SubscribedFieldName, this->bSubscribed); 167 | 168 | OnConfigUpdated.Broadcast(this); 169 | } 170 | 171 | bool UStomtConfig::GetLoggedIn() 172 | { 173 | return this->bLoggedIn; 174 | } 175 | 176 | void UStomtConfig::SetLoggedIn(bool bNewLoggedIn) 177 | { 178 | if (this->bLoggedIn == bNewLoggedIn) return; 179 | 180 | this->bLoggedIn = bNewLoggedIn; 181 | 182 | this->SaveFlag(this->LoggedInFieldName, this->bLoggedIn); 183 | 184 | OnConfigUpdated.Broadcast(this); 185 | } 186 | 187 | bool UStomtConfig::GetAcceptScreenshotUpload() 188 | { 189 | return this->bAcceptScreenshotUpload; 190 | } 191 | 192 | void UStomtConfig::SetAcceptScreenshotUpload(bool bNewAcceptScreenshotUpload) 193 | { 194 | if (this->bAcceptScreenshotUpload == bNewAcceptScreenshotUpload) return; 195 | 196 | this->bAcceptScreenshotUpload = bNewAcceptScreenshotUpload; 197 | 198 | this->SaveFlag(this->ScreenshotUploadFieldName, this->bAcceptScreenshotUpload); 199 | 200 | OnConfigUpdated.Broadcast(this); 201 | } 202 | 203 | bool UStomtConfig::GetAcceptLogUpload() 204 | { 205 | return this->bAcceptLogUpload; 206 | } 207 | 208 | void UStomtConfig::SetAcceptLogUpload(bool bNewAcceptLogUpload) 209 | { 210 | if (this->bAcceptLogUpload == bNewAcceptLogUpload) return; 211 | 212 | this->bAcceptLogUpload = bNewAcceptLogUpload; 213 | 214 | this->SaveFlag(this->LogUploadFieldName, this->bAcceptLogUpload); 215 | 216 | OnConfigUpdated.Broadcast(this); 217 | } 218 | 219 | TArray UStomtConfig::GetStomtsAsJson() 220 | { 221 | UStomtRestJsonObject* JsonObj = ReadStomtConfAsJson(); 222 | 223 | if (JsonObj->HasField(this->StomtsFieldName)) 224 | { 225 | return JsonObj->GetArrayField(this->StomtsFieldName); 226 | } 227 | else 228 | { 229 | return TArray(); 230 | } 231 | } 232 | 233 | TArray UStomtConfig::GetStomts() 234 | { 235 | TArray StomtObjects; 236 | UStomtRestJsonObject* JsonObj = ReadStomtConfAsJson(); 237 | 238 | if (JsonObj->HasField(this->StomtsFieldName)) 239 | { 240 | for (UStomtRestJsonObject* JObjStomt : JsonObj->GetObjectArrayField(this->StomtsFieldName)) 241 | { 242 | UStomt* StomtObject = UStomt::ConstructStomt( 243 | JObjStomt->GetStringField("target_id"), 244 | JObjStomt->GetBoolField("positive"), 245 | JObjStomt->GetStringField("text"), 246 | JObjStomt->GetStringField("details") 247 | ); 248 | 249 | StomtObjects.Add(StomtObject); 250 | } 251 | } 252 | else 253 | { 254 | return TArray(); 255 | } 256 | 257 | return StomtObjects; 258 | } 259 | 260 | bool UStomtConfig::AddStomt(UStomt* NewStomt) 261 | { 262 | return SaveStomtToConf(*NewStomt); 263 | } 264 | 265 | bool UStomtConfig::SaveAccessToken(FString NewAccessToken) 266 | { 267 | return SaveValueToStomtConf(this->AccessTokenFieldName, NewAccessToken); 268 | } 269 | 270 | bool UStomtConfig::SaveValueToStomtConf(FString FieldName, FString FieldValue) 271 | { 272 | UStomtRestJsonObject* JsonObj = ReadStomtConfAsJson(); 273 | 274 | if (JsonObj->HasField(FieldName)) 275 | { 276 | if (JsonObj->GetStringField(FieldName).Equals(FieldValue)) 277 | { 278 | return false; 279 | } 280 | 281 | JsonObj->RemoveField(FieldName); 282 | } 283 | 284 | JsonObj->SetStringField(FieldName, FieldValue); 285 | 286 | return this->WriteFile(JsonObj->EncodeJson(), this->ConfigName, this->ConfigFolder, true); 287 | } 288 | 289 | bool UStomtConfig::SaveStomtToConf(UStomt& NewStomt) 290 | { 291 | UStomtRestJsonObject* JsonObj = ReadStomtConfAsJson(); 292 | 293 | UStomtRestJsonObject* JObjStomt = UStomtRestJsonObject::ConstructJsonObject(this); 294 | TArray Labels = TArray(); 295 | 296 | for (int i = 0; i != NewStomt.GetLabels().Num(); ++i) 297 | { 298 | if (!NewStomt.GetLabels()[i]->GetName().IsEmpty()) 299 | { 300 | Labels.Add(UStomtJsonValue::ConstructJsonValueString(this, NewStomt.GetLabels()[i]->GetName())); 301 | } 302 | } 303 | 304 | JObjStomt->SetField(TEXT("target_id"), UStomtJsonValue::ConstructJsonValueString(this, NewStomt.GetTargetId())); 305 | JObjStomt->SetField(TEXT("positive"), UStomtJsonValue::ConstructJsonValueBool(this, NewStomt.GetPositive())); 306 | JObjStomt->SetField(TEXT("text"), UStomtJsonValue::ConstructJsonValueString(this, NewStomt.GetText())); 307 | JObjStomt->SetField(TEXT("anonym"), UStomtJsonValue::ConstructJsonValueBool(this, NewStomt.GetAnonym())); 308 | JObjStomt->SetArrayField(TEXT("labels"), Labels); 309 | 310 | if (!JsonObj->HasField(StomtsFieldName)) 311 | { 312 | TArray JObjArray1; 313 | JObjArray1.Add(JObjStomt); 314 | JsonObj->SetObjectArrayField(StomtsFieldName, JObjArray1); 315 | 316 | UE_LOG(StomtNetwork, Log, TEXT("Add Offline Stomt: To new field")); 317 | } 318 | else 319 | { 320 | TArray JObjArray2; 321 | JObjArray2 = JsonObj->GetObjectArrayField(StomtsFieldName); 322 | JObjArray2.Add(JObjStomt); 323 | JsonObj->SetObjectArrayField(StomtsFieldName, JObjArray2); 324 | UE_LOG(StomtNetwork, Log, TEXT("Add Offline Stomt: To existing field")); 325 | } 326 | 327 | UE_LOG(StomtNetwork, Log, TEXT("Add offline stomt: %s"), *JsonObj->EncodeJson()); 328 | 329 | return this->WriteFile(JsonObj->EncodeJson(), this->ConfigName, this->ConfigFolder, true); 330 | } 331 | 332 | bool UStomtConfig::ClearStomts() 333 | { 334 | UStomtRestJsonObject* JsonObj = ReadStomtConfAsJson(); 335 | 336 | if (JsonObj->HasField(StomtsFieldName)) 337 | { 338 | UE_LOG(StomtNetwork, Log, TEXT("Clear offline stomts")); 339 | JsonObj->GetArrayField(StomtsFieldName).Empty(); 340 | JsonObj->RemoveField(StomtsFieldName); 341 | } 342 | else 343 | { 344 | return true; 345 | } 346 | 347 | return this->WriteFile(JsonObj->EncodeJson(), this->ConfigName, this->ConfigFolder, true); 348 | } 349 | 350 | bool UStomtConfig::SaveFlag(FString FlagName, bool bFlagState) 351 | { 352 | return SaveValueToStomtConf(FlagName, bFlagState ? TEXT("true") : TEXT("false")); 353 | } 354 | 355 | FString UStomtConfig::ReadStomtConf(FString FieldName) 356 | { 357 | FString Result; 358 | 359 | if (this->ReadFile(Result, this->ConfigName, this->ConfigFolder)) 360 | { 361 | UStomtRestJsonObject* JsonObj = UStomtRestJsonObject::ConstructJsonObject(this); 362 | JsonObj->DecodeJson(Result); 363 | this->AccessToken = JsonObj->GetField(FieldName)->AsString(); 364 | } 365 | 366 | return Result; 367 | } 368 | 369 | bool UStomtConfig::ReadFlag(FString FlagName) 370 | { 371 | FString Result; 372 | bool bFlagState = false; 373 | 374 | if (this->ReadFile(Result, this->ConfigName, this->ConfigFolder)) 375 | { 376 | UStomtRestJsonObject* JsonObj = UStomtRestJsonObject::ConstructJsonObject(this); 377 | JsonObj->DecodeJson(Result); 378 | bFlagState = JsonObj->GetField(FlagName)->AsBool(); 379 | } 380 | 381 | return bFlagState; 382 | } 383 | 384 | UStomtRestJsonObject* UStomtConfig::ReadStomtConfAsJson() 385 | { 386 | FString Result; 387 | UStomtRestJsonObject* JsonObj = UStomtRestJsonObject::ConstructJsonObject(this); 388 | 389 | if (this->ReadFile(Result, this->ConfigName, this->ConfigFolder)) 390 | { 391 | JsonObj->DecodeJson(Result); 392 | } 393 | 394 | return JsonObj; 395 | } 396 | 397 | FString UStomtConfig::ReadAccessToken() 398 | { 399 | UStomtRestJsonObject* StomtConfigJson = this->ReadStomtConfAsJson(); 400 | 401 | if (StomtConfigJson->HasField(this->AccessTokenFieldName)) 402 | { 403 | return StomtConfigJson->GetStringField(this->AccessTokenFieldName); 404 | } 405 | 406 | return FString(TEXT("")); 407 | } 408 | 409 | bool UStomtConfig::WriteStomtConfAsJson(UStomtRestJsonObject * StomtConf) 410 | { 411 | return this->WriteFile(StomtConf->EncodeJson(), this->ConfigName, this->ConfigFolder, true); 412 | } 413 | 414 | void UStomtConfig::DeleteStomtConf() 415 | { 416 | FString File = this->ConfigFolder + this->ConfigName; 417 | if (!FPlatformFileManager::Get().GetPlatformFile().DeleteFile(*File)) 418 | { 419 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not delete stomt.conf.json: %s"), *File); 420 | } 421 | else 422 | { 423 | UE_LOG(StomtFileAccess, Warning, TEXT("Deleted stomt.conf.json because of wrong access token Path: %s"), *File); 424 | } 425 | } 426 | 427 | FString UStomtConfig::ReadLogFile(FString LogFileName) 428 | { 429 | FString ErrorLog; 430 | 431 | FString LogFilePath = FPaths::ProjectLogDir() + LogFileName; 432 | FString LogFileCopyPath = FPaths::ProjectLogDir() + LogFileName + TEXT("Copy.log"); 433 | FString LogFileCopyName = LogFileName + TEXT("Copy.log"); 434 | 435 | IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); 436 | PlatformFile.BypassSecurity(true); 437 | 438 | // Copy LogFileData 439 | if (!PlatformFile.CopyFile(*LogFileCopyPath, *LogFilePath, EPlatformFileRead::AllowWrite, EPlatformFileWrite::AllowRead)) 440 | { 441 | UE_LOG(StomtFileAccess, Warning, TEXT("LogFile Copy did not work FromFile: %s | ToFile %s"), *LogFilePath, *LogFileCopyPath); 442 | } 443 | 444 | // Read LogFileCopy from Disk 445 | if (!this->ReadFile(ErrorLog, LogFileCopyName, FPaths::ProjectLogDir())) 446 | { 447 | if (FPaths::FileExists(FPaths::ProjectLogDir() + LogFileCopyName)) 448 | { 449 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not read LogFile %s, but it exists"), *LogFileCopyName); 450 | } 451 | else 452 | { 453 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not read LogFile %s, because it does not exist"), *LogFileCopyName); 454 | } 455 | } 456 | 457 | // Delete LogFileCopy 458 | if (!PlatformFile.DeleteFile(*LogFileCopyPath)) 459 | { 460 | UE_LOG(StomtFileAccess, Warning, TEXT("Could not delete LogFileCopy %s"), *LogFileCopyPath); 461 | } 462 | 463 | return ErrorLog; 464 | } 465 | 466 | bool UStomtConfig::WriteFile(FString TextToSave, FString FileName, FString SaveDirectory, bool bAllowOverwriting) 467 | { 468 | IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile(); 469 | 470 | // CreateDirectoryTree returns true if the destination 471 | // directory existed prior to call or has been created 472 | // during the call. 473 | if (PlatformFile.CreateDirectoryTree(*SaveDirectory)) 474 | { 475 | // Get absolute file path 476 | FString AbsoluteFilePath = SaveDirectory + "/" + FileName; 477 | 478 | // Allow overwriting or file doesn't already exist 479 | if (bAllowOverwriting || !FPaths::FileExists(*AbsoluteFilePath)) 480 | { 481 | // Use " FFileHelper::EEncodingOptions::AutoDetect, &IFileManager::Get(), EFileWrite::FILEWRITE_Append);" for append 482 | return FFileHelper::SaveStringToFile(TextToSave, *AbsoluteFilePath); 483 | } 484 | } 485 | 486 | return false; 487 | } 488 | 489 | bool UStomtConfig::ReadFile(FString& Result, FString FileName, FString SaveDirectory) 490 | { 491 | FString Path = SaveDirectory + FileName; 492 | 493 | if (!FPaths::FileExists(Path)) 494 | { 495 | UE_LOG(StomtFileAccess, Warning, TEXT("File with this path does not exist: %s "), *Path); 496 | } 497 | 498 | return FFileHelper::LoadFileToString(Result, *Path); 499 | } 500 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtJsonObject.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtJsonObject.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | 7 | typedef TJsonWriterFactory< TCHAR, TCondensedJsonPrintPolicy > FCondensedJsonStringWriterFactory; 8 | typedef TJsonWriter< TCHAR, TCondensedJsonPrintPolicy > FCondensedJsonStringWriter; 9 | 10 | UStomtRestJsonObject::UStomtRestJsonObject() 11 | { 12 | Reset(); 13 | } 14 | 15 | UStomtRestJsonObject* UStomtRestJsonObject::ConstructJsonObject(UObject* WorldContextObject) 16 | { 17 | return NewObject(); 18 | } 19 | 20 | void UStomtRestJsonObject::Reset() 21 | { 22 | if (JsonObj.IsValid()) 23 | { 24 | JsonObj.Reset(); 25 | } 26 | 27 | JsonObj = MakeShareable(new FJsonObject()); 28 | } 29 | 30 | TSharedPtr& UStomtRestJsonObject::GetRootObject() 31 | { 32 | return JsonObj; 33 | } 34 | 35 | void UStomtRestJsonObject::SetRootObject(TSharedPtr& JsonObject) 36 | { 37 | JsonObj = JsonObject; 38 | } 39 | 40 | 41 | //////////////////////////////////////////////////////////////////////////// 42 | //// Serialization 43 | 44 | FString UStomtRestJsonObject::EncodeJson() const 45 | { 46 | if (!JsonObj.IsValid()) 47 | { 48 | return TEXT(""); 49 | } 50 | 51 | FString OutputString; 52 | TSharedRef< FCondensedJsonStringWriter > Writer = FCondensedJsonStringWriterFactory::Create(&OutputString); 53 | FJsonSerializer::Serialize(JsonObj.ToSharedRef(), Writer); 54 | 55 | return OutputString; 56 | } 57 | 58 | FString UStomtRestJsonObject::EncodeJsonToSingleString() const 59 | { 60 | FString OutputString = EncodeJson(); 61 | 62 | // Remove line terminators 63 | OutputString.Replace(LINE_TERMINATOR, TEXT("")); 64 | 65 | // Remove tabs 66 | OutputString.Replace(LINE_TERMINATOR, TEXT("\t")); 67 | 68 | return OutputString; 69 | } 70 | 71 | bool UStomtRestJsonObject::DecodeJson(const FString& JsonString) 72 | { 73 | TSharedRef< TJsonReader<> > Reader = TJsonReaderFactory<>::Create(*JsonString); 74 | if (FJsonSerializer::Deserialize(Reader, JsonObj) && JsonObj.IsValid()) 75 | { 76 | return true; 77 | } 78 | 79 | // If we've failed to deserialize the string, we should clear our internal data 80 | Reset(); 81 | 82 | UE_LOG(StomtLog, Error, TEXT("Json decoding failed for: %s"), *JsonString); 83 | 84 | return false; 85 | } 86 | 87 | 88 | //////////////////////////////////////////////////////////////////////////// 89 | //// FJsonObject API 90 | // 91 | TArray UStomtRestJsonObject::GetFieldNames() 92 | { 93 | TArray Result; 94 | 95 | if (!JsonObj.IsValid()) 96 | { 97 | return Result; 98 | } 99 | 100 | JsonObj->Values.GetKeys(Result); 101 | 102 | return Result; 103 | } 104 | 105 | bool UStomtRestJsonObject::HasField(const FString& FieldName) const 106 | { 107 | if (!JsonObj.IsValid()) 108 | { 109 | return false; 110 | } 111 | 112 | return JsonObj->HasField(FieldName); 113 | } 114 | 115 | void UStomtRestJsonObject::RemoveField(const FString& FieldName) 116 | { 117 | if (!JsonObj.IsValid()) 118 | { 119 | return; 120 | } 121 | 122 | JsonObj->RemoveField(FieldName); 123 | } 124 | 125 | UStomtJsonValue* UStomtRestJsonObject::GetField(const FString& FieldName) const 126 | { 127 | if (!JsonObj.IsValid()) 128 | { 129 | return NULL; 130 | } 131 | 132 | TSharedPtr NewVal = JsonObj->TryGetField(FieldName); 133 | 134 | UStomtJsonValue* NewValue = NewObject(); 135 | NewValue->SetRootValue(NewVal); 136 | 137 | return NewValue; 138 | } 139 | 140 | void UStomtRestJsonObject::SetField(const FString& FieldName, UStomtJsonValue* JsonValue) 141 | { 142 | if (!JsonObj.IsValid()) 143 | { 144 | return; 145 | } 146 | 147 | JsonObj->SetField(FieldName, JsonValue->GetRootValue()); 148 | } 149 | 150 | 151 | //////////////////////////////////////////////////////////////////////////// 152 | //// FJsonObject API Helpers (easy to use with simple Json objects) 153 | 154 | float UStomtRestJsonObject::GetNumberField(const FString& FieldName) const 155 | { 156 | if (!JsonObj.IsValid()) 157 | { 158 | return 0.0f; 159 | } 160 | 161 | return JsonObj->GetNumberField(FieldName); 162 | } 163 | 164 | void UStomtRestJsonObject::SetNumberField(const FString& FieldName, float Number) 165 | { 166 | if (!JsonObj.IsValid()) 167 | { 168 | return; 169 | } 170 | 171 | JsonObj->SetNumberField(FieldName, Number); 172 | } 173 | 174 | FString UStomtRestJsonObject::GetStringField(const FString& FieldName) const 175 | { 176 | if (!JsonObj.IsValid()) 177 | { 178 | return TEXT(""); 179 | } 180 | 181 | return JsonObj->GetStringField(FieldName); 182 | } 183 | 184 | void UStomtRestJsonObject::SetStringField(const FString& FieldName, const FString& StringValue) 185 | { 186 | if (!JsonObj.IsValid()) 187 | { 188 | return; 189 | } 190 | 191 | JsonObj->SetStringField(FieldName, StringValue); 192 | } 193 | 194 | bool UStomtRestJsonObject::GetBoolField(const FString& FieldName) const 195 | { 196 | if (!JsonObj.IsValid()) 197 | { 198 | return false; 199 | } 200 | 201 | return JsonObj->GetBoolField(FieldName); 202 | } 203 | 204 | void UStomtRestJsonObject::SetBoolField(const FString& FieldName, bool InValue) 205 | { 206 | if (!JsonObj.IsValid()) 207 | { 208 | return; 209 | } 210 | 211 | JsonObj->SetBoolField(FieldName, InValue); 212 | } 213 | 214 | TArray UStomtRestJsonObject::GetArrayField(const FString& FieldName) 215 | { 216 | TArray OutArray; 217 | if (!JsonObj.IsValid()) 218 | { 219 | return OutArray; 220 | } 221 | 222 | 223 | TArray< TSharedPtr > ValArray = JsonObj->GetArrayField(FieldName); 224 | for (auto Value : ValArray) 225 | { 226 | UStomtJsonValue* NewValue = NewObject(); 227 | NewValue->SetRootValue(Value); 228 | 229 | OutArray.Add(NewValue); 230 | } 231 | 232 | return OutArray; 233 | } 234 | 235 | void UStomtRestJsonObject::SetArrayField(const FString& FieldName, const TArray& InArray) 236 | { 237 | if (!JsonObj.IsValid()) 238 | { 239 | return; 240 | } 241 | 242 | TArray< TSharedPtr > ValArray; 243 | 244 | // Process input array and COPY original values 245 | for (auto InVal : InArray) 246 | { 247 | TSharedPtr JsonVal = InVal->GetRootValue(); 248 | 249 | switch (InVal->GetType()) 250 | { 251 | case StomtEnumJson::None: 252 | break; 253 | 254 | case StomtEnumJson::Null: 255 | ValArray.Add(MakeShareable(new FJsonValueNull())); 256 | break; 257 | 258 | case StomtEnumJson::String: 259 | ValArray.Add(MakeShareable(new FJsonValueString(JsonVal->AsString()))); 260 | break; 261 | 262 | case StomtEnumJson::Number: 263 | ValArray.Add(MakeShareable(new FJsonValueNumber(JsonVal->AsNumber()))); 264 | break; 265 | 266 | case StomtEnumJson::Boolean: 267 | ValArray.Add(MakeShareable(new FJsonValueBoolean(JsonVal->AsBool()))); 268 | break; 269 | 270 | case StomtEnumJson::Array: 271 | ValArray.Add(MakeShareable(new FJsonValueArray(JsonVal->AsArray()))); 272 | break; 273 | 274 | case StomtEnumJson::Object: 275 | ValArray.Add(MakeShareable(new FJsonValueObject(JsonVal->AsObject()))); 276 | break; 277 | 278 | default: 279 | break; 280 | } 281 | } 282 | 283 | JsonObj->SetArrayField(FieldName, ValArray); 284 | } 285 | 286 | void UStomtRestJsonObject::MergeJsonObject(UStomtRestJsonObject* InJsonObject, bool Overwrite) 287 | { 288 | TArray Keys = InJsonObject->GetFieldNames(); 289 | 290 | for (auto Key : Keys) 291 | { 292 | if (Overwrite == false && HasField(Key)) 293 | { 294 | continue; 295 | } 296 | 297 | SetField(Key, InJsonObject->GetField(Key)); 298 | } 299 | } 300 | 301 | UStomtRestJsonObject* UStomtRestJsonObject::GetObjectField(const FString& FieldName) const 302 | { 303 | if (!JsonObj.IsValid()) 304 | { 305 | return NULL; 306 | } 307 | 308 | if ( !JsonObj->HasField(FieldName) ) 309 | { 310 | return NULL; 311 | } 312 | 313 | TSharedPtr JsonObjField = JsonObj->GetObjectField(FieldName); 314 | 315 | UStomtRestJsonObject* OutRestJsonObj = NewObject(); 316 | OutRestJsonObj->SetRootObject(JsonObjField); 317 | 318 | return OutRestJsonObj; 319 | } 320 | 321 | void UStomtRestJsonObject::SetObjectField(const FString& FieldName, UStomtRestJsonObject* JsonObject) 322 | { 323 | if (!JsonObj.IsValid()) 324 | { 325 | return; 326 | } 327 | 328 | JsonObj->SetObjectField(FieldName, JsonObject->GetRootObject()); 329 | } 330 | 331 | 332 | //////////////////////////////////////////////////////////////////////////// 333 | //// Array fields helpers (uniform arrays) 334 | 335 | TArray UStomtRestJsonObject::GetNumberArrayField(const FString& FieldName) 336 | { 337 | TArray NumberArray; 338 | 339 | if (!JsonObj.IsValid()) 340 | { 341 | return NumberArray; 342 | } 343 | 344 | TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); 345 | for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) 346 | { 347 | NumberArray.Add((*It)->AsNumber()); 348 | } 349 | 350 | return NumberArray; 351 | } 352 | 353 | void UStomtRestJsonObject::SetNumberArrayField(const FString& FieldName, const TArray& NumberArray) 354 | { 355 | if (!JsonObj.IsValid()) 356 | { 357 | return; 358 | } 359 | 360 | TArray< TSharedPtr > EntriesArray; 361 | 362 | for (auto Number : NumberArray) 363 | { 364 | EntriesArray.Add(MakeShareable(new FJsonValueNumber(Number))); 365 | } 366 | 367 | JsonObj->SetArrayField(FieldName, EntriesArray); 368 | } 369 | 370 | TArray UStomtRestJsonObject::GetStringArrayField(const FString& FieldName) 371 | { 372 | TArray StringArray; 373 | 374 | if (!JsonObj.IsValid()) 375 | { 376 | return StringArray; 377 | } 378 | 379 | TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); 380 | for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) 381 | { 382 | StringArray.Add((*It)->AsString()); 383 | } 384 | 385 | return StringArray; 386 | } 387 | 388 | void UStomtRestJsonObject::SetStringArrayField(const FString& FieldName, const TArray& StringArray) 389 | { 390 | if (!JsonObj.IsValid()) 391 | { 392 | return; 393 | } 394 | 395 | TArray< TSharedPtr > EntriesArray; 396 | 397 | for (auto String : StringArray) 398 | { 399 | EntriesArray.Add(MakeShareable(new FJsonValueString(String))); 400 | } 401 | 402 | JsonObj->SetArrayField(FieldName, EntriesArray); 403 | } 404 | 405 | TArray UStomtRestJsonObject::GetBoolArrayField(const FString& FieldName) 406 | { 407 | TArray BoolArray; 408 | 409 | if (!JsonObj.IsValid()) 410 | { 411 | return BoolArray; 412 | } 413 | 414 | TArray > JsonArrayValues = JsonObj->GetArrayField(FieldName); 415 | for (TArray >::TConstIterator It(JsonArrayValues); It; ++It) 416 | { 417 | BoolArray.Add((*It)->AsBool()); 418 | } 419 | 420 | return BoolArray; 421 | } 422 | 423 | void UStomtRestJsonObject::SetBoolArrayField(const FString& FieldName, const TArray& BoolArray) 424 | { 425 | if (!JsonObj.IsValid()) 426 | { 427 | return; 428 | } 429 | 430 | TArray< TSharedPtr > EntriesArray; 431 | 432 | for (auto Boolean : BoolArray) 433 | { 434 | EntriesArray.Add(MakeShareable(new FJsonValueBoolean(Boolean))); 435 | } 436 | 437 | JsonObj->SetArrayField(FieldName, EntriesArray); 438 | } 439 | 440 | TArray UStomtRestJsonObject::GetObjectArrayField(const FString& FieldName) 441 | { 442 | TArray OutArray; 443 | 444 | if (!JsonObj.IsValid()) 445 | { 446 | return OutArray; 447 | } 448 | 449 | TArray< TSharedPtr > ValArray = JsonObj->GetArrayField(FieldName); 450 | for (auto Value : ValArray) 451 | { 452 | TSharedPtr NewObj = Value->AsObject(); 453 | 454 | UStomtRestJsonObject* NewJson = NewObject(); 455 | NewJson->SetRootObject(NewObj); 456 | 457 | OutArray.Add(NewJson); 458 | } 459 | 460 | return OutArray; 461 | } 462 | 463 | void UStomtRestJsonObject::SetObjectArrayField(const FString& FieldName, const TArray& ObjectArray) 464 | { 465 | if (!JsonObj.IsValid()) 466 | { 467 | return; 468 | } 469 | 470 | TArray< TSharedPtr > EntriesArray; 471 | 472 | for (auto Value : ObjectArray) 473 | { 474 | EntriesArray.Add(MakeShareable(new FJsonValueObject(Value->GetRootObject()))); 475 | } 476 | 477 | JsonObj->SetArrayField(FieldName, EntriesArray); 478 | } 479 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtJsonValue.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtJsonValue.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | 7 | UStomtJsonValue* UStomtJsonValue::ConstructJsonValueNumber(UObject* WorldContextObject, float Number) 8 | { 9 | TSharedPtr NewVal = MakeShareable(new FJsonValueNumber(Number)); 10 | 11 | UStomtJsonValue* NewValue = NewObject(); 12 | NewValue->SetRootValue(NewVal); 13 | 14 | return NewValue; 15 | } 16 | 17 | UStomtJsonValue* UStomtJsonValue::ConstructJsonValueString(UObject* WorldContextObject, const FString& StringValue) 18 | { 19 | TSharedPtr NewVal = MakeShareable(new FJsonValueString(StringValue)); 20 | 21 | UStomtJsonValue* NewValue = NewObject(); 22 | NewValue->SetRootValue(NewVal); 23 | 24 | return NewValue; 25 | } 26 | 27 | UStomtJsonValue* UStomtJsonValue::ConstructJsonValueBool(UObject* WorldContextObject, bool InValue) 28 | { 29 | TSharedPtr NewVal = MakeShareable(new FJsonValueBoolean(InValue)); 30 | 31 | UStomtJsonValue* NewValue = NewObject(); 32 | NewValue->SetRootValue(NewVal); 33 | 34 | return NewValue; 35 | } 36 | 37 | UStomtJsonValue* UStomtJsonValue::ConstructJsonValueArray(UObject* WorldContextObject, const TArray& InArray) 38 | { 39 | // Prepare data array to create new value 40 | TArray< TSharedPtr > ValueArray; 41 | for (auto InVal : InArray) 42 | { 43 | ValueArray.Add(InVal->GetRootValue()); 44 | } 45 | 46 | TSharedPtr NewVal = MakeShareable(new FJsonValueArray(ValueArray)); 47 | 48 | UStomtJsonValue* NewValue = NewObject(); 49 | NewValue->SetRootValue(NewVal); 50 | 51 | return NewValue; 52 | } 53 | 54 | UStomtJsonValue* ConstructJsonValue(UObject* WorldContextObject, const TSharedPtr& InValue) 55 | { 56 | TSharedPtr NewVal = InValue; 57 | 58 | UStomtJsonValue* NewValue = NewObject(); 59 | NewValue->SetRootValue(NewVal); 60 | 61 | return NewValue; 62 | } 63 | 64 | TSharedPtr& UStomtJsonValue::GetRootValue() 65 | { 66 | return JsonVal; 67 | } 68 | 69 | void UStomtJsonValue::SetRootValue(TSharedPtr& JsonValue) 70 | { 71 | JsonVal = JsonValue; 72 | } 73 | 74 | 75 | //////////////////////////////////////////////////////////////////////////// 76 | //// FJsonValue API 77 | 78 | StomtEnumJson::Type UStomtJsonValue::GetType() const 79 | { 80 | if (!(JsonVal.IsValid())) 81 | { 82 | return StomtEnumJson::None; 83 | } 84 | 85 | switch (JsonVal->Type) 86 | { 87 | case EJson::None: 88 | return StomtEnumJson::None; 89 | 90 | case EJson::Null: 91 | return StomtEnumJson::Null; 92 | 93 | case EJson::String: 94 | return StomtEnumJson::String; 95 | 96 | case EJson::Number: 97 | return StomtEnumJson::Number; 98 | 99 | case EJson::Boolean: 100 | return StomtEnumJson::Boolean; 101 | 102 | case EJson::Array: 103 | return StomtEnumJson::Array; 104 | 105 | case EJson::Object: 106 | return StomtEnumJson::Object; 107 | 108 | default: 109 | return StomtEnumJson::None; 110 | } 111 | } 112 | 113 | FString UStomtJsonValue::GetTypeString() const 114 | { 115 | if (!JsonVal.IsValid()) 116 | { 117 | return "None"; 118 | } 119 | 120 | switch (JsonVal->Type) 121 | { 122 | case EJson::None: 123 | return TEXT("None"); 124 | 125 | case EJson::Null: 126 | return TEXT("Null"); 127 | 128 | case EJson::String: 129 | return TEXT("String"); 130 | 131 | case EJson::Number: 132 | return TEXT("Number"); 133 | 134 | case EJson::Boolean: 135 | return TEXT("Boolean"); 136 | 137 | case EJson::Array: 138 | return TEXT("Array"); 139 | 140 | case EJson::Object: 141 | return TEXT("Object"); 142 | 143 | default: 144 | return TEXT("None"); 145 | } 146 | } 147 | 148 | bool UStomtJsonValue::IsNull() const 149 | { 150 | if (!JsonVal.IsValid()) 151 | { 152 | return true; 153 | } 154 | 155 | return JsonVal->IsNull(); 156 | } 157 | 158 | float UStomtJsonValue::AsNumber() const 159 | { 160 | if (!JsonVal.IsValid()) 161 | { 162 | ErrorMessage(TEXT("Number")); 163 | return 0.f; 164 | } 165 | 166 | return JsonVal->AsNumber(); 167 | } 168 | 169 | FString UStomtJsonValue::AsString() const 170 | { 171 | if (!JsonVal.IsValid()) 172 | { 173 | ErrorMessage(TEXT("String")); 174 | return FString(); 175 | } 176 | 177 | return JsonVal->AsString(); 178 | } 179 | 180 | bool UStomtJsonValue::AsBool() const 181 | { 182 | if (!JsonVal.IsValid()) 183 | { 184 | ErrorMessage(TEXT("Boolean")); 185 | return false; 186 | } 187 | 188 | return JsonVal->AsBool(); 189 | } 190 | 191 | TArray UStomtJsonValue::AsArray() const 192 | { 193 | TArray OutArray; 194 | 195 | if (!JsonVal.IsValid()) 196 | { 197 | ErrorMessage(TEXT("Array")); 198 | return OutArray; 199 | } 200 | 201 | TArray< TSharedPtr > ValArray = JsonVal->AsArray(); 202 | for (auto Value : ValArray) 203 | { 204 | UStomtJsonValue* NewValue = NewObject(); 205 | NewValue->SetRootValue(Value); 206 | 207 | OutArray.Add(NewValue); 208 | } 209 | 210 | return OutArray; 211 | } 212 | 213 | 214 | // 215 | //////////////////////////////////////////////////////////////////////////// 216 | //// Helpers 217 | // 218 | void UStomtJsonValue::ErrorMessage(const FString& InType) const 219 | { 220 | UE_LOG(StomtLog, Error, TEXT("Json Value of type '%s' used as a '%s'."), *GetTypeString(), *InType); 221 | } 222 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtLabel.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtLabel.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | 7 | ////////////////////////////////////////////////////////////////////////// 8 | // Construction 9 | 10 | UStomtLabel::UStomtLabel() 11 | { 12 | // Default 13 | /* 14 | this->Color = FString("#5EBEFF"); 15 | this->bIsPublic = false; 16 | this->bAsTargetOwner = false; 17 | */ 18 | } 19 | 20 | ////////////////////////////////////////////////////////////////////////// 21 | // Data accessors 22 | 23 | UStomtLabel * UStomtLabel::ConstructLabel(FString NewName) 24 | { 25 | UStomtLabel* StomtLabel = NewObject(); 26 | StomtLabel->SetName(NewName); 27 | 28 | return StomtLabel; 29 | } 30 | 31 | void UStomtLabel::SetName(FString NewName) 32 | { 33 | this->Name = NewName; 34 | } 35 | 36 | void UStomtLabel::SetColor(FString NewColor) 37 | { 38 | this->Color = NewColor; 39 | } 40 | 41 | void UStomtLabel::SetIsPublic(bool bNewIsPublic) 42 | { 43 | this->bIsPublic = bNewIsPublic; 44 | } 45 | 46 | void UStomtLabel::SetAsTargetOwner(bool bNewAsTargetOwner) 47 | { 48 | this->bAsTargetOwner = bNewAsTargetOwner; 49 | } 50 | 51 | FString UStomtLabel::GetName() 52 | { 53 | return this->Name; 54 | } 55 | 56 | FString UStomtLabel::GetColor() 57 | { 58 | return this->Color; 59 | } 60 | 61 | bool UStomtLabel::GetIsPublic() 62 | { 63 | return this->bIsPublic; 64 | } 65 | 66 | bool UStomtLabel::GetAsTargetOwner() 67 | { 68 | return this->bAsTargetOwner; 69 | } 70 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtPlugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | #include "StomtPlugin.h" 4 | #include "StomtPluginPrivatePCH.h" 5 | 6 | class FStomtPlugin : public StomtPlugin 7 | { 8 | /** IModuleInterface implementation */ 9 | virtual void StartupModule() override 10 | { 11 | //Force classes to be compiled on shipping build 12 | } 13 | 14 | virtual void ShutdownModule() override 15 | { 16 | 17 | } 18 | }; 19 | 20 | IMPLEMENT_MODULE(FStomtPlugin, StomtPlugin); 21 | 22 | DEFINE_LOG_CATEGORY(StomtLog); 23 | DEFINE_LOG_CATEGORY(StomtNetwork); 24 | DEFINE_LOG_CATEGORY(StomtInit); 25 | DEFINE_LOG_CATEGORY(StomtFileAccess); 26 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtPluginWidget.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginWidget.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | #include "StomtRestRequest.h" 7 | #include "StomtLabel.h" 8 | 9 | #include "Runtime/Engine/Classes/Components/SceneCaptureComponent2D.h" 10 | 11 | UStomtPluginWidget::~UStomtPluginWidget() 12 | { 13 | this->LoginErrorCode = 0; 14 | } 15 | 16 | void UStomtPluginWidget::OnConstruction(FString AppId) 17 | { 18 | // Create API Object 19 | if (this->Api == NULL) 20 | { 21 | this->Api = UStomtAPI::ConstructStomtAPI(AppId); 22 | } 23 | else 24 | { 25 | this->Api->SetAppId(AppId); 26 | } 27 | 28 | this->Config = this->Api->Config; 29 | 30 | // Request User 31 | this->Api->RequestSession(); 32 | 33 | // Request Target Name 34 | UStomtRestRequest* Request = this->Api->RequestTargetByAppId(); 35 | Request->OnRequestComplete.AddDynamic(this, &UStomtPluginWidget::OnTargetResponse); 36 | 37 | // Lookup E-Mail 38 | this->bIsEMailAlreadyKnown = this->Api->Config->GetSubscribed(); 39 | this->bIsUserLoggedIn = this->Api->Config->GetLoggedIn(); 40 | } 41 | 42 | void UStomtPluginWidget::OnMessageChanged(FString text) 43 | { 44 | if (!text.IsEmpty()) 45 | { 46 | this->Message = text; 47 | } 48 | else 49 | { 50 | this->Message = FString(TEXT("")); 51 | } 52 | } 53 | 54 | 55 | void UStomtPluginWidget::OnDetailsCommitted(FString text) 56 | { 57 | if (!text.IsEmpty()) 58 | { 59 | this->Details = text; 60 | } 61 | else 62 | { 63 | this->Details = FString(TEXT("")); 64 | } 65 | } 66 | 67 | void UStomtPluginWidget::OnSubmit() 68 | { 69 | if (this->Message.IsEmpty()) 70 | { 71 | return; 72 | } 73 | 74 | // Check EMail 75 | this->bIsEMailAlreadyKnown = this->Api->Config->GetSubscribed(); 76 | UE_LOG(StomtLog, Log, TEXT("Is EMail Already Known: %s"), this->bIsEMailAlreadyKnown ? TEXT("true") : TEXT("false")); 77 | 78 | // Create Stomt Instance 79 | this->Stomt = UStomt::ConstructStomt(this->Api->GetTargetId(), !this->bIsWish, this->Message, this->Details); 80 | this->Stomt->SetLabels(this->Labels); 81 | this->Stomt->SetAnonym(false); 82 | 83 | this->Api->SetStomtToSend(this->Stomt); 84 | this->Api->HandleOfflineStomts(); 85 | 86 | if (this->bUploadLogs) 87 | { 88 | FString LogFileName = FApp::GetProjectName() + FString(TEXT(".log")); 89 | FString LogFile = this->Api->ReadLogFile(LogFileName); 90 | if (!LogFile.IsEmpty()) 91 | { 92 | this->Api->SendLogFile(LogFile, LogFileName); 93 | return; 94 | } 95 | } 96 | 97 | this->Api->bIsLogUploadComplete = true; 98 | if (!this->Api->bUseImageUpload) 99 | { 100 | this->Api->SendStomt(this->Stomt); 101 | } // else Screenhot Upload is triggered by blueprint 102 | } 103 | 104 | void UStomtPluginWidget::OnSubmitLastLayer() 105 | { 106 | 107 | } 108 | 109 | bool UStomtPluginWidget::OnSubmitLogin() 110 | { 111 | if (!this->UserName.IsEmpty() && !this->UserPassword.IsEmpty()) 112 | { 113 | UStomtRestRequest* Request = this->Api->SendLoginRequest(this->UserName, this->UserPassword); 114 | Request->OnRequestComplete.AddDynamic(this, &UStomtPluginWidget::OnLoginResponse); 115 | this->LoginErrorCode = 0; 116 | return true; 117 | } 118 | else 119 | { 120 | return false; 121 | } 122 | } 123 | 124 | void UStomtPluginWidget::OnSubmitEMail() 125 | { 126 | if (!this->EMail.IsEmpty()) 127 | { 128 | this->Api->SendSubscription(this->EMail, !this->bUsePhoneNumber); 129 | } 130 | } 131 | 132 | void UStomtPluginWidget::OnLogout() 133 | { 134 | this->Api->SendLogoutRequest(); 135 | } 136 | 137 | void UStomtPluginWidget::OnLoginResponse(UStomtRestRequest * LoginRequest) 138 | { 139 | this->LoginErrorCode = LoginRequest->GetResponseCode(); 140 | this->bIsUserLoggedIn = this->Api->Config->GetLoggedIn(); 141 | this->Api->OnLoginRequestComplete.Broadcast(LoginRequest); 142 | } 143 | 144 | void UStomtPluginWidget::OnTargetResponse(UStomtRestRequest * TargetRequest) 145 | { 146 | this->TargetName = this->Api->GetTargetName(); 147 | 148 | UE_LOG(StomtLog, Log, TEXT("OnTargetResponse: %s"), *this->TargetName); 149 | 150 | this->ImageUrl = this->Api->GetImageUrl(); 151 | 152 | this->Api->OnTargetRequestComplete.Broadcast(TargetRequest); 153 | } 154 | 155 | FString UStomtPluginWidget::AppendStomtURLParams(FString Url, FString UtmContent) 156 | { 157 | Url += FString("?utm_source=" + FString("stomt")); 158 | Url += FString("&utm_medium=" + FString("sdk")); 159 | Url += FString("&utm_campaign=" + FString("unreal")); 160 | Url += FString("&utm_term=" + FString(FApp::GetProjectName()) ); 161 | 162 | if (!UtmContent.IsEmpty()) 163 | { 164 | Url += FString("&utm_content=" + UtmContent); 165 | } 166 | 167 | if (!this->Api->Config->GetAccessToken().IsEmpty()) 168 | { 169 | Url += FString("&accesstoken=" + this->Api->Config->GetAccessToken()); 170 | } 171 | 172 | return Url; 173 | } 174 | 175 | void UStomtPluginWidget::UploadScreenshot() 176 | { 177 | this->Api->SendImageFile(this->Api->ReadScreenshotAsBase64()); 178 | } 179 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtRestRequest.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtRestRequest.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | 7 | ////////////////////////////////////////////////////////////////////////// 8 | // Construction 9 | 10 | UStomtRestRequest::UStomtRestRequest() 11 | { 12 | this->bUseStaticJsonString = false; 13 | this->UseRequestLogging(true); 14 | this->ResponseJsonObj = NULL; 15 | this->RequestJsonObj = NULL; 16 | this->ResetData(); 17 | } 18 | 19 | UStomtRestRequest::~UStomtRestRequest() 20 | { 21 | } 22 | 23 | 24 | UStomtRestRequest * UStomtRestRequest::ConstructRequest() 25 | { 26 | return nullptr; 27 | } 28 | 29 | void UStomtRestRequest::SetVerb(StomtEnumRequestVerb::Type Verb) 30 | { 31 | this->RequestVerb = Verb; 32 | } 33 | 34 | void UStomtRestRequest::SetHeader(const FString &HeaderName, const FString &HeaderValue) 35 | { 36 | this->RequestHeaders.Add(HeaderName, HeaderValue); 37 | } 38 | 39 | void UStomtRestRequest::OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) 40 | { 41 | // Check we have result to process futher 42 | if (!bWasSuccessful) 43 | { 44 | UE_LOG(StomtNetwork, Error, TEXT("Request failed: %s ResponseCode: %d "), *Request->GetURL(), *Response->GetContentAsString()); 45 | 46 | // Broadcast the result event 47 | this->OnRequestFail.Broadcast(this); 48 | return; 49 | } 50 | 51 | if (EHttpResponseCodes::IsOk(Response->GetResponseCode())) 52 | { 53 | UE_LOG(StomtNetwork, Log, TEXT("EHttpResponseCodes::IsOk")); 54 | UE_LOG(StomtNetwork, Log, TEXT("Content: %s"), *Response->GetContentAsString() ); 55 | } 56 | else 57 | { 58 | UE_LOG(StomtNetwork, Warning, TEXT( "not successful: %s"), *Response->GetContentAsString() ); 59 | } 60 | 61 | return; 62 | } 63 | 64 | ////////////////////////////////////////////////////////////////////////// 65 | // Helpers 66 | 67 | 68 | 69 | /////////////////////////////////////////////////////////////////////////// 70 | // Response data access 71 | 72 | int32 UStomtRestRequest::GetResponseCode() 73 | { 74 | return this->ResponseCode; 75 | } 76 | 77 | FString UStomtRestRequest::GetResponseHeader(const FString HeaderName) 78 | { 79 | FString Result; 80 | 81 | FString* Header = ResponseHeaders.Find(HeaderName); 82 | if (Header != NULL) 83 | { 84 | Result = *Header; 85 | } 86 | 87 | return Result; 88 | } 89 | 90 | 91 | TArray UStomtRestRequest::GetAllResponseHeaders() 92 | { 93 | TArray Result; 94 | 95 | for (TMap::TConstIterator It(ResponseHeaders); It; ++It) 96 | { 97 | Result.Add(It.Key() + TEXT(": ") + It.Value()); 98 | } 99 | 100 | return Result; 101 | } 102 | 103 | ////////////////////////////////////////////////////////////////////////// 104 | // URL processing 105 | 106 | void UStomtRestRequest::ProcessUrl(const FString& Url) 107 | { 108 | // Signature changed from version 4.25 to 4.26 (ThreadSafe) 109 | auto HttpRequest = FHttpModule::Get().CreateRequest(); 110 | HttpRequest->SetURL(Url); 111 | 112 | // Set verb 113 | switch (RequestVerb) 114 | { 115 | case StomtEnumRequestVerb::GET: 116 | HttpRequest->SetVerb(TEXT("GET")); 117 | break; 118 | 119 | case StomtEnumRequestVerb::POST: 120 | HttpRequest->SetVerb(TEXT("POST")); 121 | break; 122 | 123 | case StomtEnumRequestVerb::PUT: 124 | HttpRequest->SetVerb(TEXT("PUT")); 125 | break; 126 | 127 | case StomtEnumRequestVerb::DEL: 128 | HttpRequest->SetVerb(TEXT("DELETE")); 129 | break; 130 | 131 | default: 132 | break; 133 | } 134 | 135 | HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); 136 | 137 | // Serialize data to json string 138 | FString OutputString; 139 | TSharedRef< TJsonWriter<> > Writer = TJsonWriterFactory<>::Create(&OutputString); 140 | FJsonSerializer::Serialize(this->RequestJsonObj->GetRootObject().ToSharedRef(), Writer); 141 | 142 | 143 | // Set Json content 144 | if ( !HttpRequest->GetVerb().Equals( TEXT("GET") ) ) 145 | { 146 | if (this->bUseStaticJsonString) 147 | { 148 | if (!this->StaticJsonOutputString.IsEmpty()) 149 | { 150 | OutputString = this->StaticJsonOutputString; 151 | } 152 | } 153 | 154 | HttpRequest->SetContentAsString(OutputString); 155 | } 156 | 157 | if (this->bRequestLogging) 158 | { 159 | if (OutputString.Len() > 256) 160 | { 161 | FString shortContent = OutputString.LeftChop(OutputString.Len() - 256); 162 | UE_LOG(StomtNetwork, Log, TEXT("Request (json): %s %s | truncated-content(256): %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *shortContent); 163 | } 164 | else 165 | { 166 | UE_LOG(StomtNetwork, Log, TEXT("Request (json): %s %s %s"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *OutputString); 167 | } 168 | } 169 | else 170 | { 171 | UE_LOG(StomtNetwork, Log, TEXT("Request (json): %s %s | did not log (contains user data)"), *HttpRequest->GetVerb(), *HttpRequest->GetURL()); 172 | } 173 | 174 | 175 | 176 | // Apply additional headers 177 | for (TMap::TConstIterator It(RequestHeaders); It; ++It) 178 | { 179 | HttpRequest->SetHeader(It.Key(), It.Value()); 180 | } 181 | 182 | // Bind event 183 | HttpRequest->OnProcessRequestComplete().BindUObject(this, &UStomtRestRequest::OnProcessRequestComplete); 184 | 185 | // Execute the Request 186 | HttpRequest->ProcessRequest(); 187 | } 188 | 189 | 190 | ////////////////////////////////////////////////////////////////////////// 191 | // Request callbacks 192 | 193 | 194 | void UStomtRestRequest::OnProcessRequestComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful) 195 | { 196 | // Be sure that we have no data from previous response 197 | this->ResetResponseData(); 198 | 199 | // Check we have result to process futher 200 | if (!bWasSuccessful) 201 | { 202 | UE_LOG(StomtNetwork, Error, TEXT("Request failed: %s"), *Request->GetURL()); 203 | 204 | // Broadcast the result event 205 | this->OnRequestFail.Broadcast(this); 206 | return; 207 | } 208 | 209 | // Save response data as a string 210 | this->ResponseContent = Response->GetContentAsString(); 211 | 212 | // Save response code as int32 213 | this->ResponseCode = Response->GetResponseCode(); 214 | 215 | // Log response state 216 | 217 | if (Response->GetContentAsString().Len() > 256) 218 | { 219 | FString shortContent = Response->GetContentAsString().LeftChop(Response->GetContentAsString().Len() - 256); 220 | UE_LOG(StomtNetwork, Log, TEXT("Response (%d): Content(truncated 256): %s"), Response->GetResponseCode(), *shortContent); 221 | } 222 | else 223 | { 224 | UE_LOG(StomtNetwork, Log, TEXT("Response (%d): %s"), Response->GetResponseCode(), *Response->GetContentAsString()); 225 | } 226 | 227 | 228 | // Process response headers 229 | TArray Headers = Response->GetAllHeaders(); 230 | for (FString Header : Headers) 231 | { 232 | FString Key; 233 | FString Value; 234 | if (Header.Split(TEXT(": "), &Key, &Value)) 235 | { 236 | this->ResponseHeaders.Add(Key, Value); 237 | } 238 | } 239 | 240 | // Try to deserialize data to JSON 241 | TSharedRef> JsonReader = TJsonReaderFactory::Create(this->ResponseContent); 242 | FJsonSerializer::Deserialize(JsonReader, this->ResponseJsonObj->GetRootObject()); 243 | 244 | // Decide whether the Request was successful 245 | this->bIsValidJsonResponse = bWasSuccessful && this->ResponseJsonObj->GetRootObject().IsValid(); 246 | 247 | // Log errors 248 | if (!this->bIsValidJsonResponse) 249 | { 250 | if (!this->ResponseJsonObj->GetRootObject().IsValid()) 251 | { 252 | // As we assume it's recommended way to use current class, but not the only one, 253 | // it will be the warning instead of error 254 | UE_LOG(StomtNetwork, Warning, TEXT("JSON could not be decoded!")); 255 | } 256 | } 257 | 258 | // Broadcast the result event 259 | this->OnRequestComplete.Broadcast(this); 260 | 261 | // Finish the latent action 262 | if (this->ContinueAction) 263 | { 264 | StomtLatentAction *K = this->ContinueAction; 265 | this->ContinueAction = nullptr; 266 | 267 | K->Call(this->ResponseJsonObj); 268 | } 269 | } 270 | 271 | void UStomtRestRequest::UseStaticJsonString(bool bNewUseStaticJsonString) 272 | { 273 | this->bUseStaticJsonString = bNewUseStaticJsonString; 274 | } 275 | 276 | void UStomtRestRequest::UseRequestLogging(bool bNewRequestLogging) 277 | { 278 | this->bRequestLogging = bNewRequestLogging; 279 | } 280 | 281 | void UStomtRestRequest::SetStaticJsonString(FString JsonString) 282 | { 283 | this->StaticJsonOutputString = JsonString; 284 | } 285 | 286 | ////////////////////////////////////////////////////////////////////////// 287 | // Destruction and reset 288 | 289 | void UStomtRestRequest::ResetData() 290 | { 291 | this->ResetRequestData(); 292 | this->ResetResponseData(); 293 | } 294 | 295 | void UStomtRestRequest::ResetRequestData() 296 | { 297 | if (this->RequestJsonObj != NULL) 298 | { 299 | this->RequestJsonObj->Reset(); 300 | } 301 | else 302 | { 303 | this->RequestJsonObj = NewObject(); 304 | } 305 | 306 | this->bUseStaticJsonString = false; 307 | } 308 | 309 | void UStomtRestRequest::ResetResponseData() 310 | { 311 | if (this->ResponseJsonObj != NULL) 312 | { 313 | this->ResponseJsonObj->Reset(); 314 | } 315 | else 316 | { 317 | this->ResponseJsonObj = NewObject(); 318 | } 319 | 320 | this->ResponseHeaders.Empty(); 321 | this->ResponseCode = -1; 322 | 323 | this->bIsValidJsonResponse = false; 324 | } 325 | 326 | 327 | ////////////////////////////////////////////////////////////////////////// 328 | // JSON data accessors 329 | 330 | UStomtRestJsonObject* UStomtRestRequest::GetRequestObject() 331 | { 332 | return this->RequestJsonObj; 333 | } 334 | 335 | void UStomtRestRequest::SetRequestObject(UStomtRestJsonObject* JsonObject) 336 | { 337 | this->RequestJsonObj = JsonObject; 338 | } 339 | 340 | UStomtRestJsonObject* UStomtRestRequest::GetResponseObject() 341 | { 342 | return this->ResponseJsonObj; 343 | } 344 | 345 | void UStomtRestRequest::SetResponseObject(UStomtRestJsonObject* JsonObject) 346 | { 347 | ResponseJsonObj = JsonObject; 348 | } 349 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Private/StomtTrack.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtTrack.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | #include "StomtJsonObject.h" 7 | 8 | #include "Runtime/Core/Public/Misc/FileHelper.h" 9 | #include "Runtime/Core/Public/Misc/Paths.h" 10 | #include "Runtime/Core/Public/GenericPlatform/GenericPlatformFile.h" 11 | #include "Runtime/Core/Public/Misc/App.h" 12 | #include "Runtime/Engine/Classes/Kismet/GameplayStatics.h" 13 | #include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h" 14 | #include "Runtime/Core/Public/GenericPlatform/GenericPlatformProcess.h" 15 | #include "Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h" 16 | 17 | UStomtTrack* UStomtTrack::ConstructStomtTrack() 18 | { 19 | UStomtTrack* Track = NewObject(); 20 | return Track; 21 | } 22 | 23 | UStomtTrack::UStomtTrack() 24 | { 25 | UE_LOG(StomtInit, Log, TEXT("Constuct Stomt Sdk Track")); 26 | 27 | this->SetDevicePlatform(UGameplayStatics::GetPlatformName()); 28 | UE_LOG(StomtInit, Log, TEXT("DevicePlatform: %s"), *this->DevicePlatform); 29 | 30 | this->SetDeviceId(FGenericPlatformProcess::ComputerName()); 31 | UE_LOG(StomtInit, Log, TEXT("DeviceId: %s"), *this->DeviceId); 32 | 33 | this->SetSdkType(FString("UnrealEngine") + UKismetSystemLibrary::GetEngineVersion()); 34 | UE_LOG(StomtInit, Log, TEXT("SdkType: %s"), *this->SdkType); 35 | 36 | this->SetSdkVersion("2.5.1"); 37 | UE_LOG(StomtInit, Log, TEXT("SdkVersion: %s"), *this->SdkVersion); 38 | 39 | this->SetSdkIntegration(UKismetSystemLibrary::GetGameName()); 40 | UE_LOG(StomtInit, Log, TEXT("SdkIntegration: %s"), *this->SdkIntegration); 41 | } 42 | 43 | UStomtTrack::~UStomtTrack() 44 | { 45 | 46 | } 47 | 48 | UStomtRestJsonObject * UStomtTrack::GetAsJsonObject() 49 | { 50 | UStomtRestJsonObject* JsonObj = UStomtRestJsonObject::ConstructJsonObject(this); 51 | 52 | if (!this->DevicePlatform.IsEmpty()) 53 | { 54 | JsonObj->SetStringField("device_platform", this->DevicePlatform); 55 | } 56 | 57 | if (!this->DeviceId.IsEmpty()) 58 | { 59 | JsonObj->SetStringField("device_id", this->DeviceId); 60 | } 61 | 62 | if (!this->SdkType.IsEmpty()) 63 | { 64 | JsonObj->SetStringField("sdk_type", this->SdkType); 65 | } 66 | 67 | if (!this->SdkVersion.IsEmpty()) 68 | { 69 | JsonObj->SetStringField("sdk_version", this->SdkVersion); 70 | } 71 | 72 | if (!this->SdkIntegration.IsEmpty()) 73 | { 74 | JsonObj->SetStringField("sdk_integration", this->SdkIntegration); 75 | } 76 | 77 | if (!this->TargetId.IsEmpty()) 78 | { 79 | JsonObj->SetStringField("target_id", this->TargetId); 80 | } 81 | 82 | if (!this->StomtId.IsEmpty()) 83 | { 84 | JsonObj->SetStringField("stomt_id", this->StomtId); 85 | } 86 | 87 | if (!this->EventCategory.IsEmpty()) 88 | { 89 | JsonObj->SetStringField("event_category", this->EventCategory); 90 | } 91 | 92 | if (!this->EventAction.IsEmpty()) 93 | { 94 | JsonObj->SetStringField("event_action", this->EventAction); 95 | } 96 | 97 | if (!this->EventLabel.IsEmpty()) 98 | { 99 | JsonObj->SetStringField("event_label", this->EventLabel); 100 | } 101 | 102 | return JsonObj; 103 | } 104 | 105 | void UStomtTrack::SetDevicePlatform(FString NewDevicePlatform) 106 | { 107 | this->DevicePlatform = NewDevicePlatform; 108 | } 109 | 110 | void UStomtTrack::SetDeviceId(FString NewDeviceId) 111 | { 112 | this->DeviceId = NewDeviceId; 113 | } 114 | 115 | void UStomtTrack::SetSdkType(FString NewSdkType) 116 | { 117 | this->SdkType = NewSdkType; 118 | } 119 | 120 | void UStomtTrack::SetSdkVersion(FString NewSdkVersion) 121 | { 122 | this->SdkVersion = NewSdkVersion; 123 | } 124 | 125 | void UStomtTrack::SetSdkIntegration(FString NewSdkIntegration) 126 | { 127 | this->SdkIntegration = NewSdkIntegration; 128 | } 129 | 130 | void UStomtTrack::SetTargetId(FString NewTargetId) 131 | { 132 | this->TargetId = NewTargetId; 133 | } 134 | 135 | void UStomtTrack::SetStomtId(FString NewStomtId) 136 | { 137 | this->StomtId = NewStomtId; 138 | } 139 | 140 | void UStomtTrack::SetEventCategory(FString NewEventCategory) 141 | { 142 | this->EventCategory = NewEventCategory; 143 | } 144 | 145 | void UStomtTrack::SetEventAction(FString NewEventAction) 146 | { 147 | this->EventAction = NewEventAction; 148 | } 149 | 150 | void UStomtTrack::SetEventLabel(FString NewEventLabel) 151 | { 152 | this->EventLabel = NewEventLabel; 153 | } 154 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/Stomt.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginPrivatePCH.h" 5 | #include "StomtRestRequest.h" 6 | #include "StomtLabel.h" 7 | #include "Stomt.generated.h" 8 | 9 | UCLASS() 10 | class STOMTPLUGIN_API UStomt : public UObject 11 | { 12 | GENERATED_BODY() 13 | 14 | public: 15 | ////////////////////////////////////////////////////////////////////////// 16 | // Construction 17 | 18 | UStomt(); 19 | 20 | /** 21 | * Creates new Stomt object 22 | * @param NewTargetId - Stomt target Id 23 | * @param bNewPositive - whether it is wish(false) or like(true) 24 | * @param NewText - Stomt content text. 25 | * @param NewDetails - Stomt details text. 26 | */ 27 | static UStomt* ConstructStomt(FString NewTargetId, bool bNewPositive, FString NewText, FString NewDetails); 28 | 29 | ////////////////////////////////////////////////////////////////////////// 30 | // Destruction and reset 31 | //TODO reset functions 32 | 33 | ////////////////////////////////////////////////////////////////////////// 34 | // Data accessors 35 | 36 | void SetTargetId(FString NewTargetId); 37 | 38 | void SetPositive(bool bNewPositive); 39 | 40 | void SetText(FString NewText); 41 | 42 | void SetDetails(FString NewDetails); 43 | 44 | void SetAnonym(bool bNewAnonym); 45 | 46 | void SetServersideId(FString NewServersideId); 47 | 48 | // Labels 49 | void AddLabel(UStomtLabel* NewLabel); 50 | 51 | void SetLabels(TArray NewLabels); 52 | 53 | void SetLabels(TArray NewLabels); 54 | 55 | FString GetTargetId(); 56 | 57 | bool GetPositive(); 58 | 59 | FString GetText(); 60 | 61 | FString GetDetails(); 62 | 63 | bool GetAnonym(); 64 | 65 | TArray GetLabels(); 66 | 67 | FString GetServersideId(); 68 | 69 | 70 | 71 | ////////////////////////////////////////////////////////////////////////// 72 | // Data 73 | 74 | private: 75 | UPROPERTY() 76 | FString ServersideId; 77 | 78 | UPROPERTY() 79 | FString TargetId; 80 | 81 | UPROPERTY() 82 | bool bPositive; 83 | 84 | UPROPERTY() 85 | FString Text; 86 | 87 | UPROPERTY() 88 | FString Url; 89 | 90 | UPROPERTY() 91 | FString Details; 92 | 93 | UPROPERTY() 94 | bool bAnonym; 95 | 96 | UPROPERTY() 97 | FString ImgName; 98 | 99 | UPROPERTY() 100 | FString LonLat; 101 | 102 | UPROPERTY() 103 | TArray Labels; 104 | }; 105 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtAPI.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginPrivatePCH.h" 5 | #include "StomtRestRequest.h" 6 | #include "Stomt.h" 7 | #include "StomtConfig.h" 8 | #include "StomtTrack.h" 9 | #include "Runtime/Engine/Classes/Engine/TextureRenderTarget2D.h" 10 | #include "StomtAPI.generated.h" 11 | 12 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTargetRequestComplete, class UStomtRestRequest*, Request); 13 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLoginRequestComplete, class UStomtRestRequest*, Request); 14 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestFailed, class UStomtRestRequest*, Request); 15 | 16 | UCLASS() 17 | class STOMTPLUGIN_API UStomtAPI : public UObject 18 | { 19 | GENERATED_BODY() 20 | 21 | public: 22 | 23 | static UStomtAPI* ConstructStomtAPI(FString AppId); 24 | 25 | UStomtAPI(); 26 | 27 | ~UStomtAPI(); 28 | 29 | /** 30 | * Sends a stomt. 31 | * @param stomt - Stomt Object with some content. 32 | */ 33 | void SendStomt(UStomt* Stomt); 34 | 35 | ////////////////////////////////////////////////////////////////////////// 36 | // Data accessors 37 | 38 | /** 39 | * Sets the STOMT REST API Server URL. 40 | * For example: https://rest.stomt.com 41 | * @param URL - Stomt REST URL 42 | */ 43 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 44 | void SetRestUrl(FString NewRestUrl); 45 | 46 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 47 | FString GetRestUrl(); 48 | 49 | /** 50 | * Sets the STOMT Website Server URL. 51 | * For example: https://www.stomt.com 52 | * @param URL - Stomt REST URL 53 | */ 54 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 55 | void SetStomtUrl(FString NewStomtUrl); 56 | 57 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 58 | FString GetStomtUrl(); 59 | 60 | /** 61 | * Sets the Stomt App ID. 62 | * That was created here: https://www.stomt.com/dev/my-apps 63 | * @param AppID - Stomt APP ID 64 | */ 65 | void SetAppId(FString NewAppId); 66 | 67 | FString GetAppId(); 68 | 69 | /** 70 | * Returns the Target-Name that can be displayed. 71 | * Only call this after a target was requested. 72 | */ 73 | FString GetTargetName(); 74 | 75 | /** 76 | * Sets a Stomt Target 77 | * @param TargetID - ID of Stomt Target 78 | */ 79 | void SetTargetId(FString NewTargetId); 80 | 81 | FString GetTargetId(); 82 | 83 | /** 84 | * Sets the URL for the target image. 85 | * @param URL - Target-Image URL 86 | */ 87 | void SetImageUrl(FString NewImageUrl); 88 | 89 | FString GetImageUrl(); 90 | 91 | void SetStomtToSend(UStomt* Stomt); 92 | 93 | /** 94 | * Gets the Request object that contains Request/response information. 95 | */ 96 | UStomtRestRequest* GetRequest(); 97 | 98 | ////////////////////////////////////////////////////////////////////////// 99 | // Stomt File Access 100 | 101 | /** 102 | * Loads an Log file from disk. 103 | * @param LogFileName - Log File Name. 104 | */ 105 | FString ReadLogFile(FString LogFileName); 106 | 107 | ////////////////////////////////////////////////////////////////////////// 108 | // Network 109 | 110 | UFUNCTION() 111 | void OnSendStomtRequestResponse(UStomtRestRequest * Request); 112 | 113 | UStomtRestRequest* SendLoginRequest(FString UserName, FString Password); 114 | 115 | UFUNCTION() 116 | void OnLoginRequestResponse(UStomtRestRequest * Request); 117 | 118 | UStomtRestRequest* RequestSession(); 119 | 120 | UFUNCTION() 121 | void OnRequestSessionResponse(UStomtRestRequest * Request); 122 | 123 | /** 124 | * Sends an REST Request for a stomt target. 125 | */ 126 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 127 | UStomtRestRequest* RequestTargetByAppId(); 128 | 129 | /** 130 | * Sends an REST Request for a stomt target. 131 | * To receive the respose it is necessary to add a event delegate function. 132 | * For example: api->GetRequest()->OnRequestComplete.AddDynamic(this, &UStomtPluginWidget::OnLoginRequestResponse). 133 | * @param TargetID - ID of the requested stomt target. 134 | */ 135 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 136 | UStomtRestRequest* RequestTarget(FString TargetId); 137 | 138 | UFUNCTION() 139 | void OnRequestTargetResponse(UStomtRestRequest * Request); 140 | 141 | /** 142 | * Sends the LogFileData to stomt.com server. 143 | */ 144 | void SendLogFile(FString LogFileData, FString LogFileName); 145 | 146 | UFUNCTION() 147 | void OnSendLogFileResponse(UStomtRestRequest * Request); 148 | 149 | /** 150 | * Sends the Image to stomt.com server. 151 | */ 152 | void SendImageFile(FString ImageFileDataBase64); 153 | 154 | UFUNCTION() 155 | void OnSendImageFileResponse(UStomtRestRequest * Request); 156 | 157 | void SendSubscription(FString EMail); 158 | 159 | void SendSubscription(FString EMailOrNumber, bool bUseEmail); 160 | 161 | UFUNCTION() 162 | void OnSendEMailResponse(UStomtRestRequest * Request); 163 | 164 | void SendLogoutRequest(); 165 | 166 | UFUNCTION() 167 | void OnSendLogoutResponse(UStomtRestRequest * Request); 168 | 169 | ////////////////////////////////////////////////////////////////////////// 170 | // Track SDK Usage 171 | 172 | UFUNCTION(BlueprintCallable, Category = "Stomt Track") 173 | void SendTrack(UStomtTrack* NewTrack); 174 | 175 | 176 | ////////////////////////////////////////////////////////////////////////// 177 | // Screenshot 178 | 179 | UFUNCTION() 180 | FString ReadScreenshotAsBase64(); 181 | 182 | ////////////////////////////////////////////////////////////////////////// 183 | // Request callbacks 184 | 185 | public: 186 | /** Event occured when the Request has been completed */ 187 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 188 | FOnTargetRequestComplete OnSessionRequestComplete; 189 | 190 | /** Event occured when the Request has been completed */ 191 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 192 | FOnTargetRequestComplete OnTargetRequestComplete; 193 | 194 | /** Event occured when the Request has been completed */ 195 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 196 | FOnLoginRequestComplete OnLoginRequestComplete; 197 | 198 | /** Event occured when the Request has been completed */ 199 | //UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 200 | //FOnRequestComplete OnRequestComplete; // ToDo Trigger this 201 | 202 | /** Event occured when the Request wasn't successfull */ 203 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 204 | FOnRequestFailed OnRequestFailed; 205 | 206 | UFUNCTION() 207 | void OnARequestFailed(UStomtRestRequest* Request); 208 | 209 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 210 | bool IsConnected(); 211 | 212 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 213 | void ConnectionTest(); 214 | 215 | ////////////////////////////////////////////////////////////////////////// 216 | // Data 217 | public: 218 | 219 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt API") 220 | UStomtConfig* Config; 221 | 222 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt API") 223 | UStomtTrack* Track; 224 | 225 | UStomt* StomtToSend; 226 | 227 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt API") 228 | FString ImageUploadName; 229 | 230 | FString ErrorLogFileUid; 231 | 232 | FString DefaultScreenshotName; 233 | 234 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 235 | bool bUseImageUpload; 236 | 237 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 238 | bool bUseDefaultLabels; 239 | 240 | bool bIsLogUploadComplete; 241 | 242 | bool bIsImageUploadComplete; 243 | 244 | bool bLoginRequestWasSend; 245 | 246 | bool bEMailFlagWasSend; 247 | 248 | bool bLogFileWasSend; 249 | 250 | bool bNetworkError; 251 | 252 | FString RestUrl; 253 | 254 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 255 | FString StomtUrl; 256 | 257 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 258 | FString TargetName; 259 | 260 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 261 | FString TargetId; 262 | 263 | FString AppId; 264 | 265 | FString ImageUrl; 266 | 267 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 268 | int StomtsCreatedByUser; 269 | 270 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 271 | int StomtsReceivedByTarget; 272 | 273 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stomt API") 274 | FString UserId; 275 | 276 | ////////////////////////////////////////////////////////////////////////// 277 | // Multi-Language 278 | 279 | public: 280 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 281 | UStomtRestJsonObject* LoadLanguageFile(); 282 | 283 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 284 | FString GetLangText(FString Text); 285 | 286 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 287 | FString GetCurrentLanguage(); 288 | 289 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 290 | bool SetCurrentLanguage(FString newLanguage); 291 | 292 | private: 293 | FString GetSystemLanguage(); 294 | 295 | FString LoadLanguageFileContent(); 296 | 297 | UPROPERTY() 298 | UStomtRestJsonObject* Languages; 299 | 300 | UPROPERTY() 301 | FString CurrentLanguage; 302 | 303 | ////////////////////////////////////////////////////////////////////////// 304 | // Helper Functions 305 | 306 | public: 307 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 308 | bool IsEmailCorrect(FString Email); 309 | 310 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 311 | bool DoesScreenshotFileExist(); 312 | 313 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 314 | void UseScreenshotUpload(bool bUseUpload); 315 | 316 | void AddCustomKeyValuePair(FString key, FString value); 317 | 318 | void HandleOfflineStomts(); 319 | 320 | UFUNCTION(BlueprintCallable, Category = "Stomt API") 321 | void SendOfflineStomts(); 322 | 323 | private: 324 | bool WriteFile(FString TextToSave, FString FileName, FString SaveDirectory, bool bAllowOverwriting); 325 | 326 | bool ReadFile(FString& Result, FString FileName, FString SaveDirectory); 327 | 328 | TArray ReadBinaryFile(FString FilePath); 329 | 330 | UStomtRestRequest* SetupNewRequest(StomtEnumRequestVerb::Type Verb); 331 | 332 | void AddAccesstokenToRequest(UStomtRestRequest* Request); 333 | 334 | UFUNCTION() 335 | void ParseAccessTokenFromResponse(UStomtRestRequest * Request); 336 | 337 | TArray> CustomKeyValuePairs; 338 | }; 339 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtConfig.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | #include "StomtJsonObject.h" 4 | #include "Stomt.h" 5 | #include "StomtPluginPrivatePCH.h" 6 | #include "StomtRestRequest.h" 7 | #include "StomtConfig.generated.h" 8 | 9 | 10 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnConfigUpdated, class UStomtConfig*, Config); 11 | 12 | UCLASS() 13 | class UStomtConfig : public UObject 14 | { 15 | GENERATED_BODY() 16 | 17 | public: 18 | 19 | static UStomtConfig* ConstructStomtConfig(); 20 | 21 | UStomtConfig(); 22 | 23 | ~UStomtConfig(); 24 | ////////////////////////////////////////////////////////////////////////// 25 | // Public 26 | 27 | /** 28 | * checks if a config file exists, creates one or reads it 29 | **/ 30 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 31 | void Load(); 32 | 33 | /** 34 | * deletes to current config file 35 | **/ 36 | void Delete(); 37 | 38 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 39 | FString GetAccessToken(); 40 | 41 | void SetAccessToken(FString NewAccessToken); 42 | 43 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 44 | bool GetSubscribed(); 45 | 46 | void SetSubscribed(bool bNewSubscribed); 47 | 48 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 49 | bool GetLoggedIn(); 50 | 51 | void SetLoggedIn(bool bNewLoggedIn); 52 | 53 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 54 | bool GetAcceptScreenshotUpload(); 55 | 56 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 57 | void SetAcceptScreenshotUpload(bool bNewAcceptScreenshotUpload); 58 | 59 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 60 | bool GetAcceptLogUpload(); 61 | 62 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 63 | void SetAcceptLogUpload(bool bNewAcceptLogUpload); 64 | 65 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 66 | FOnConfigUpdated OnConfigUpdated; 67 | 68 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 69 | TArray GetStomtsAsJson(); 70 | 71 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 72 | TArray GetStomts(); 73 | 74 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 75 | bool AddStomt(UStomt* NewStomt); 76 | 77 | /** 78 | * Clears the stomt array in /stomt/stomt.conf.json 79 | */ 80 | bool ClearStomts(); 81 | 82 | private: 83 | 84 | ////////////////////////////////////////////////////////////////////////// 85 | // Read Config 86 | 87 | /** 88 | * Loads the access token from disk. 89 | */ 90 | FString ReadStomtConf(FString FieldName); 91 | 92 | /** 93 | * Loads the flag from disk. 94 | */ 95 | bool ReadFlag(FString FlagName); 96 | 97 | /** 98 | * Loads the access token from disk. 99 | */ 100 | UStomtRestJsonObject* ReadStomtConfAsJson(); 101 | 102 | /** 103 | * Loads the access token from disk. 104 | */ 105 | FString ReadAccessToken(); 106 | 107 | ////////////////////////////////////////////////////////////////////////// 108 | // Write Config 109 | 110 | /** 111 | * Saves the access token in /stomt/stomt.conf.json 112 | */ 113 | bool SaveAccessToken(FString NewAccessToken); 114 | 115 | /** 116 | * Saves the a value in /stomt/stomt.conf.json 117 | */ 118 | bool SaveValueToStomtConf(FString FieldName, FString FieldValue); 119 | 120 | /** 121 | * Saves the a stomt in /stomt/stomt.conf.json 122 | */ 123 | bool SaveStomtToConf(UStomt& NewStomt); 124 | 125 | /** 126 | * Saves the flag in /stomt/stomt.conf.json 127 | */ 128 | bool SaveFlag(FString FlagName, bool bFlagState); 129 | 130 | /** 131 | * Loads the access token from disk. 132 | */ 133 | bool WriteStomtConfAsJson(UStomtRestJsonObject* StomtConf); 134 | 135 | /** 136 | * Delete stomt.conf.json 137 | */ 138 | void DeleteStomtConf(); 139 | 140 | /** 141 | * Loads an Log file from disk. 142 | * @param LogFileName - Log File Name. 143 | */ 144 | FString ReadLogFile(FString LogFileName); 145 | 146 | bool WriteFile(FString TextToSave, FString FileName, FString SaveDirectory, bool AllowOverwriting); 147 | 148 | bool ReadFile(FString& Result, FString FileName, FString SaveDirectory); 149 | 150 | ////////////////////////////////////////////////////////////////////////// 151 | // Data 152 | 153 | bool bSubscribed; 154 | bool bLoggedIn; 155 | bool bAcceptLogUpload; 156 | bool bAcceptScreenshotUpload; 157 | 158 | FString SubscribedFieldName; 159 | FString LoggedInFieldName; 160 | FString AccessTokenFieldName; 161 | FString StomtsFieldName; 162 | FString LogUploadFieldName; 163 | FString ScreenshotUploadFieldName; 164 | 165 | FString AccessToken; 166 | FString ConfigFolder; 167 | FString ConfigName; 168 | 169 | UPROPERTY() 170 | TArray Stomts; 171 | }; 172 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtJsonObject.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtJsonValue.h" 5 | #include "StomtJsonObject.generated.h" 6 | 7 | /** 8 | * Blueprintable FJsonObject wrapper 9 | */ 10 | UCLASS() 11 | class UStomtRestJsonObject : public UObject 12 | { 13 | GENERATED_BODY() 14 | 15 | public: 16 | 17 | UStomtRestJsonObject(); 18 | 19 | /** Create new Json object */ 20 | UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Object", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "Stomt|Json") 21 | static UStomtRestJsonObject* ConstructJsonObject(UObject* WorldContextObject); 22 | 23 | /** Reset all internal data */ 24 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 25 | void Reset(); 26 | 27 | /** Get the root Json object */ 28 | TSharedPtr& GetRootObject(); 29 | 30 | /** Set the root Json object */ 31 | void SetRootObject(TSharedPtr& JsonObject); 32 | 33 | 34 | // ////////////////////////////////////////////////////////////////////////// 35 | // // Serialization 36 | 37 | /** Serialize Json to string (formatted with line breaks) */ 38 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 39 | FString EncodeJson() const; 40 | 41 | /** Serialize Json to string (signel string without line breaks) */ 42 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 43 | FString EncodeJsonToSingleString() const; 44 | 45 | /** Construct Json object from string */ 46 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 47 | bool DecodeJson(const FString& JsonString); 48 | 49 | 50 | // ////////////////////////////////////////////////////////////////////////// 51 | // // FJsonObject API 52 | // 53 | /** Returns a list of field names that exist in the object */ 54 | UFUNCTION(BlueprintPure, Category = "Stomt|Json") 55 | TArray GetFieldNames(); 56 | 57 | /** Checks to see if the FieldName exists in the object */ 58 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 59 | bool HasField(const FString& FieldName) const; 60 | 61 | /** Remove field named FieldName */ 62 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 63 | void RemoveField(const FString& FieldName); 64 | 65 | /** Get the field named FieldName as a JsonValue */ 66 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 67 | UStomtJsonValue* GetField(const FString& FieldName) const; 68 | 69 | /** Add a field named FieldName with a Value */ 70 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 71 | void SetField(const FString& FieldName, UStomtJsonValue* JsonValue); 72 | 73 | /** Get the field named FieldName as a Json Array */ 74 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 75 | TArray GetArrayField(const FString& FieldName); 76 | 77 | /** Set an ObjectField named FieldName and value of Json Array */ 78 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 79 | void SetArrayField(const FString& FieldName, const TArray& InArray); 80 | 81 | /** Adds all of the fields from one json object to this one */ 82 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 83 | void MergeJsonObject(UStomtRestJsonObject* InJsonObject, bool Overwrite); 84 | 85 | 86 | // ////////////////////////////////////////////////////////////////////////// 87 | // // FJsonObject API Helpers (easy to use with simple Json objects) 88 | 89 | /** Get the field named FieldName as a number. Ensures that the field is present and is of type Json number. 90 | * Attn.!! float used instead of double to make the function blueprintable! */ 91 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 92 | float GetNumberField(const FString& FieldName) const; 93 | 94 | /** Add a field named FieldName with Number as value 95 | * Attn.!! float used instead of double to make the function blueprintable! */ 96 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 97 | void SetNumberField(const FString& FieldName, float Number); 98 | 99 | /** Get the field named FieldName as a string. */ 100 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 101 | FString GetStringField(const FString& FieldName) const; 102 | 103 | /** add a field named fieldname with value of stringvalue */ 104 | UFUNCTION(BlueprintCallable, category = "Stomt|Json") 105 | void SetStringField(const FString& Fieldname, const FString& stringvalue); 106 | 107 | /** Get the field named FieldName as a boolean. */ 108 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 109 | bool GetBoolField(const FString& FieldName) const; 110 | 111 | /** Set a boolean field named FieldName and value of InValue */ 112 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 113 | void SetBoolField(const FString& FieldName, bool InValue); 114 | 115 | /** Get the field named FieldName as a Json object. */ 116 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 117 | UStomtRestJsonObject* GetObjectField(const FString& FieldName) const; 118 | 119 | /** Set an ObjectField named FieldName and value of JsonObject */ 120 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 121 | void SetObjectField(const FString& FieldName, UStomtRestJsonObject* JsonObject); 122 | 123 | // 124 | // ////////////////////////////////////////////////////////////////////////// 125 | // // Array fields helpers (uniform arrays) 126 | 127 | /** Get the field named FieldName as a Number Array. Use it only if you're sure that array is uniform! 128 | * Attn.!! float used instead of double to make the function blueprintable! */ 129 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 130 | TArray GetNumberArrayField(const FString& FieldName); 131 | 132 | /** Set an ObjectField named FieldName and value of Number Array 133 | * Attn.!! float used instead of double to make the function blueprintable! */ 134 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 135 | void SetNumberArrayField(const FString& FieldName, const TArray& NumberArray); 136 | 137 | /** Get the field named FieldName as a String Array. Use it only if you're sure that array is uniform! */ 138 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 139 | TArray GetStringArrayField(const FString& FieldName); 140 | 141 | /** Set an ObjectField named FieldName and value of String Array */ 142 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 143 | void SetStringArrayField(const FString& FieldName, const TArray& StringArray); 144 | 145 | /** Get the field named FieldName as a Bool Array. Use it only if you're sure that array is uniform! */ 146 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 147 | TArray GetBoolArrayField(const FString& FieldName); 148 | 149 | /** Set an ObjectField named FieldName and value of Bool Array */ 150 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 151 | void SetBoolArrayField(const FString& FieldName, const TArray& BoolArray); 152 | 153 | /** Get the field named FieldName as an Object Array. Use it only if you're sure that array is uniform! */ 154 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 155 | TArray GetObjectArrayField(const FString& FieldName); 156 | 157 | /** Set an ObjectField named FieldName and value of Ob Array */ 158 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 159 | void SetObjectArrayField(const FString& FieldName, const TArray& ObjectArray); 160 | 161 | 162 | // ////////////////////////////////////////////////////////////////////////// 163 | // // Data 164 | 165 | private: 166 | /** Internal JSON data */ 167 | TSharedPtr JsonObj; 168 | 169 | }; 170 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtJsonValue.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginPrivatePCH.h" 5 | #include "StomtJsonValue.generated.h" 6 | 7 | /** 8 | * Represents all the types a Json Value can be. 9 | */ 10 | UENUM(BlueprintType) 11 | namespace StomtEnumJson 12 | { 13 | enum Type 14 | { 15 | None, 16 | Null, 17 | String, 18 | Number, 19 | Boolean, 20 | Array, 21 | Object, 22 | }; 23 | } 24 | 25 | /** 26 | * Blueprintable FJsonValue wrapper 27 | */ 28 | UCLASS(BlueprintType, Blueprintable) 29 | class UStomtJsonValue : public UObject 30 | { 31 | GENERATED_BODY() 32 | 33 | public: 34 | 35 | /** Create new Json Number value 36 | * Attn.!! float used instead of double to make the function blueprintable! */ 37 | UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Number Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "Stomt|Json") 38 | static UStomtJsonValue* ConstructJsonValueNumber(UObject* WorldContextObject, float Number); 39 | 40 | /** Create new Json String value */ 41 | UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json String Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "Stomt|Json") 42 | static UStomtJsonValue* ConstructJsonValueString(UObject* WorldContextObject, const FString& StringValue); 43 | 44 | /** Create new Json Bool value */ 45 | UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Bool Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "Stomt|Json") 46 | static UStomtJsonValue* ConstructJsonValueBool(UObject* WorldContextObject, bool InValue); 47 | 48 | /** Create new Json Array value */ 49 | UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Array Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "Stomt|Json") 50 | static UStomtJsonValue* ConstructJsonValueArray(UObject* WorldContextObject, const TArray& InArray); 51 | 52 | /** Create new Json value from FJsonValue (to be used from StomtJsonObject) */ 53 | static UStomtJsonValue* ConstructJsonValue(UObject* WorldContextObject, const TSharedPtr& InValue); 54 | 55 | /** Get the root Json value */ 56 | TSharedPtr& GetRootValue(); 57 | 58 | /** Set the root Json value */ 59 | void SetRootValue(TSharedPtr& JsonValue); 60 | 61 | 62 | ////////////////////////////////////////////////////////////////////////// 63 | // FJsonValue API 64 | 65 | /** Get type of Json value (Enum) */ 66 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 67 | StomtEnumJson::Type GetType() const; 68 | 69 | /** Get type of Json value (String) */ 70 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 71 | FString GetTypeString() const; 72 | 73 | /** Returns true if this value is a 'null' */ 74 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 75 | bool IsNull() const; 76 | 77 | /** Returns this value as a double, throwing an error if this is not an Json Number 78 | * Attn.!! float used instead of double to make the function blueprintable! */ 79 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 80 | float AsNumber() const; 81 | 82 | /** Returns this value as a number, throwing an error if this is not an Json String */ 83 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 84 | FString AsString() const; 85 | 86 | /** Returns this value as a boolean, throwing an error if this is not an Json Bool */ 87 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 88 | bool AsBool() const; 89 | 90 | /** Returns this value as an array, throwing an error if this is not an Json Array */ 91 | UFUNCTION(BlueprintCallable, Category = "Stomt|Json") 92 | TArray AsArray() const; 93 | 94 | ////////////////////////////////////////////////////////////////////////// 95 | // Data 96 | 97 | private: 98 | 99 | /** Internal JSON data */ 100 | TSharedPtr JsonVal; 101 | 102 | 103 | ////////////////////////////////////////////////////////////////////////// 104 | // Helpers 105 | 106 | protected: 107 | 108 | /** Simple error logger */ 109 | void ErrorMessage(const FString& InType) const; 110 | 111 | }; 112 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtLabel.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginPrivatePCH.h" 5 | #include "StomtLabel.generated.h" 6 | 7 | UCLASS() 8 | class UStomtLabel : public UObject 9 | { 10 | GENERATED_BODY() 11 | 12 | public: 13 | 14 | ////////////////////////////////////////////////////////////////////////// 15 | // Construction 16 | 17 | UStomtLabel(); 18 | //~UStomtLabel(); 19 | 20 | static UStomtLabel* ConstructLabel(FString NewName); 21 | 22 | 23 | ////////////////////////////////////////////////////////////////////////// 24 | // Data accessors 25 | 26 | void SetName(FString NewName); 27 | void SetColor(FString NewColor); 28 | void SetIsPublic(bool bNewIsPublic); 29 | void SetAsTargetOwner(bool bNewAsTargetOwner); 30 | 31 | FString GetName(); 32 | FString GetColor(); 33 | bool GetIsPublic(); 34 | bool GetAsTargetOwner(); 35 | 36 | private: 37 | 38 | ////////////////////////////////////////////////////////////////////////// 39 | // Data 40 | 41 | UPROPERTY() 42 | FString Name; 43 | UPROPERTY() 44 | FString Color; 45 | UPROPERTY() 46 | bool bIsPublic; 47 | UPROPERTY() 48 | bool bAsTargetOwner; 49 | 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtPlugin.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | class StomtPlugin : public IModuleInterface 5 | { 6 | 7 | public: 8 | 9 | /** 10 | * Singleton-like access to this module's interface. This is just for convenience! 11 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 12 | * 13 | * @return Returns singleton instance, loading the module on demand if needed 14 | */ 15 | static inline StomtPlugin& Get() 16 | { 17 | return FModuleManager::LoadModuleChecked< StomtPlugin >("StomtPlugin"); 18 | } 19 | 20 | /** 21 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 22 | * 23 | * @return True if the module is loaded and ready to use 24 | */ 25 | static inline bool IsAvailable() 26 | { 27 | return FModuleManager::Get().IsModuleLoaded("StomtPlugin"); 28 | } 29 | 30 | }; 31 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtPluginPrivatePCH.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "CoreUObject.h" 5 | #include "Engine.h" 6 | 7 | #include "Http.h" 8 | #include "Json.h" 9 | 10 | #include "LatentActions.h" 11 | #include "Core.h" 12 | #include "Engine.h" 13 | 14 | DECLARE_LOG_CATEGORY_EXTERN(StomtLog, Log, All); 15 | 16 | //Logging during plugin startup 17 | DECLARE_LOG_CATEGORY_EXTERN(StomtInit, Log, All); 18 | 19 | //Logging during network communication 20 | DECLARE_LOG_CATEGORY_EXTERN(StomtNetwork, Log, All); 21 | 22 | //Logging during file access 23 | DECLARE_LOG_CATEGORY_EXTERN(StomtFileAccess, Log, All); 24 | #include "StomtPlugin.h" 25 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtPluginWidget.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "Runtime/UMG/Public/UMG.h" 5 | #include "Runtime/UMG/Public/UMGStyle.h" 6 | #include "Runtime/UMG/Public/Slate/SObjectWidget.h" 7 | #include "Runtime/UMG/Public/IUMGModule.h" 8 | #include "Runtime/UMG/Public/Blueprint/UserWidget.h" 9 | 10 | #include "Blueprint/UserWidget.h" 11 | 12 | #include "StomtRestRequest.h" 13 | #include "Stomt.h" 14 | #include "StomtAPI.h" 15 | #include "StomtConfig.h" 16 | 17 | #include "StomtPluginWidget.generated.h" 18 | 19 | UCLASS() 20 | class UStomtPluginWidget : public UUserWidget 21 | { 22 | GENERATED_BODY() 23 | 24 | public: 25 | 26 | ~UStomtPluginWidget(); 27 | 28 | /** 29 | * Stomt content-text from the UI textbox. 30 | */ 31 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 32 | FString Message; 33 | 34 | /** 35 | * Stomt details-text from the UI textbox. 36 | */ 37 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 38 | FString Details; 39 | 40 | /** 41 | * EMail from the UI EMail layer. 42 | */ 43 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 44 | FString EMail; 45 | 46 | /** 47 | * UserName from the UI Login layer. 48 | */ 49 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 50 | FString UserName; 51 | 52 | /** 53 | * UserPassword from the UI Login layer. 54 | */ 55 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 56 | FString UserPassword; 57 | 58 | /** 59 | * Target-name that will be shown in the widget. 60 | */ 61 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 62 | FString TargetName; 63 | 64 | /** 65 | * Target-image URL 66 | */ 67 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 68 | FString ImageUrl; 69 | 70 | /** 71 | * STOMT API. 72 | */ 73 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 74 | UStomtAPI* Api; 75 | 76 | /** 77 | * STOMT Config. 78 | */ 79 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 80 | UStomtConfig* Config; 81 | 82 | /** 83 | * Whether the E-Mail variable is a phone number. 84 | */ 85 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 86 | bool bUsePhoneNumber; 87 | 88 | /** 89 | * Whether the stomt is not positive (a wish). 90 | */ 91 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 92 | bool bIsWish; 93 | 94 | /** 95 | * Whether a screenshot should be appended. (not implemented) 96 | */ 97 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 98 | bool bIsScreenshotSelected; 99 | 100 | /** 101 | * Whether the user mail is already known. 102 | */ 103 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 104 | bool bIsEMailAlreadyKnown; 105 | 106 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 107 | bool bIsUserLoggedIn; 108 | 109 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 110 | bool bUploadLogs; 111 | 112 | /** 113 | * Error-Code whether the user login worked. (0: OK, 403: wrong password, 404: account does not exist. ) 114 | */ 115 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 116 | int LoginErrorCode; 117 | 118 | /** 119 | * The labels which will be appended to the stomt. 120 | */ 121 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stomt Widget Plugin") 122 | TArray Labels; 123 | 124 | /** 125 | * Event when text inside the widget changed. 126 | * @param text - Current text from the widget-textbox 127 | */ 128 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 129 | void OnMessageChanged(FString text); 130 | 131 | /** 132 | * Event when details text of the widget is committed. 133 | * @param text - Current details text from the widget-textbox 134 | */ 135 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 136 | void OnDetailsCommitted(FString text); 137 | 138 | /** 139 | * Once the user sends off the stomt. 140 | */ 141 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 142 | void OnSubmit(); 143 | 144 | /** 145 | * Once the user finishes all layers. 146 | */ 147 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 148 | void OnSubmitLastLayer(); 149 | 150 | /** 151 | * Once the user finishes the login. 152 | * @return Wether the login Request was send. 153 | */ 154 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 155 | bool OnSubmitLogin(); 156 | 157 | /** 158 | * Once the user finishes the email input. 159 | */ 160 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 161 | void OnSubmitEMail(); 162 | 163 | /** 164 | * Once the user logs out. 165 | */ 166 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 167 | void OnLogout(); 168 | 169 | /** 170 | * Called at the widget startup to initialize variables. 171 | * @param TargetID - Stomt target-id 172 | * @param RestURL - Stomt REST-API URL 173 | * @param AppID - Stomt application-ID 174 | */ 175 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 176 | void OnConstruction(FString AppID); 177 | 178 | /** 179 | * Event called after the stomt server responded. 180 | * @param CurrentRequest - Stomt Request that carries the response information. 181 | */ 182 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 183 | void OnLoginResponse(UStomtRestRequest* CurrentRequest); 184 | 185 | UFUNCTION() 186 | void OnTargetResponse(UStomtRestRequest * TargetRequest); 187 | 188 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 189 | FString AppendStomtURLParams(FString url, FString utm_content); 190 | 191 | // Not ready yet. 192 | UFUNCTION(BlueprintCallable, Category = "Stomt Widget Plugin") 193 | void UploadScreenshot(); 194 | 195 | private: 196 | 197 | UPROPERTY() 198 | UStomt* Stomt; 199 | 200 | }; 201 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtRestRequest.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "StomtPluginPrivatePCH.h" 5 | #include "StomtJsonObject.h" 6 | #include "StomtRestRequest.generated.h" 7 | 8 | /** 9 | * @author Original latent action class by https://github.com/unktomi 10 | */ 11 | template class StomtLatentAction : public FPendingLatentAction 12 | { 13 | public: 14 | 15 | virtual void Call(const T &Value) 16 | { 17 | Result = Value; 18 | Called = true; 19 | } 20 | 21 | void operator()(const T &Value) 22 | { 23 | Call(Value); 24 | } 25 | 26 | void Cancel(); 27 | 28 | StomtLatentAction(FWeakObjectPtr RequestObj, T& ResultParam, const FLatentActionInfo& LatentInfo) : 29 | Called(false), 30 | Request(RequestObj), 31 | ExecutionFunction(LatentInfo.ExecutionFunction), 32 | OutputLink(LatentInfo.Linkage), 33 | CallbackTarget(LatentInfo.CallbackTarget), 34 | Result(ResultParam) 35 | { 36 | } 37 | 38 | virtual void UpdateOperation(FLatentResponse& Response) override 39 | { 40 | Response.FinishAndTriggerIf(Called, ExecutionFunction, OutputLink, CallbackTarget); 41 | } 42 | 43 | virtual void NotifyObjectDestroyed() 44 | { 45 | Cancel(); 46 | } 47 | 48 | virtual void NotifyActionAborted() 49 | { 50 | Cancel(); 51 | } 52 | 53 | private: 54 | bool Called; 55 | FWeakObjectPtr Request; 56 | 57 | public: 58 | const FName ExecutionFunction; 59 | const int32 OutputLink; 60 | const FWeakObjectPtr CallbackTarget; 61 | T &Result; 62 | 63 | }; 64 | 65 | /** Verb (GET, PUT, POST) */ 66 | UENUM(BlueprintType) 67 | namespace StomtEnumRequestVerb 68 | { 69 | enum Type 70 | { 71 | GET, 72 | POST, 73 | PUT, 74 | DEL UMETA(DisplayName = "DELETE"), 75 | }; 76 | } 77 | 78 | /** Generate a delegates for callback events */ 79 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestComplete, class UStomtRestRequest*, Request); 80 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestFail, class UStomtRestRequest*, Request); 81 | 82 | 83 | UCLASS() 84 | class UStomtRestRequest : public UObject 85 | { 86 | GENERATED_BODY() 87 | 88 | public: 89 | ////////////////////////////////////////////////////////////////////////// 90 | // Construction 91 | 92 | UStomtRestRequest(); 93 | ~UStomtRestRequest(); 94 | 95 | static UStomtRestRequest* ConstructRequest(); 96 | 97 | /** Set verb to the Request */ 98 | void SetVerb(StomtEnumRequestVerb::Type Verb); 99 | 100 | /** Sets header info */ 101 | void SetHeader(const FString &HeaderName, const FString &HeaderValue); 102 | 103 | void OnResponseReceived( 104 | FHttpRequestPtr Request, 105 | FHttpResponsePtr Response, 106 | bool bWasSuccessful); 107 | 108 | ////////////////////////////////////////////////////////////////////////// 109 | // Destruction and reset 110 | 111 | /** Reset all internal saved data */ 112 | void ResetData(); 113 | 114 | /** Reset saved Request data */ 115 | void ResetRequestData(); 116 | 117 | /** Reset saved response data */ 118 | void ResetResponseData(); 119 | 120 | /** Cancel latent response waiting */ 121 | void Cancel(); 122 | 123 | 124 | ////////////////////////////////////////////////////////////////////////// 125 | // JSON data accessors 126 | 127 | /** Get the Request Json object */ 128 | UStomtRestJsonObject* GetRequestObject(); 129 | 130 | /** Set the Request Json object */ 131 | void SetRequestObject(UStomtRestJsonObject* JsonObject); 132 | 133 | /** Get the Response Json object */ 134 | UStomtRestJsonObject* GetResponseObject(); 135 | 136 | /** Set the Response Json object */ 137 | void SetResponseObject(UStomtRestJsonObject* JsonObject); 138 | 139 | 140 | /////////////////////////////////////////////////////////////////////////// 141 | // Response data access 142 | 143 | /** Get the responce code of the last query */ 144 | int32 GetResponseCode(); 145 | 146 | /** Get value of desired response header */ 147 | FString GetResponseHeader(const FString HeaderName); 148 | 149 | /** Get list of all response headers */ 150 | TArray GetAllResponseHeaders(); 151 | 152 | 153 | ////////////////////////////////////////////////////////////////////////// 154 | // URL processing 155 | 156 | /** Open URL with current setup */ 157 | virtual void ProcessUrl(const FString& Url); 158 | 159 | 160 | ////////////////////////////////////////////////////////////////////////// 161 | // Request callbacks 162 | 163 | private: 164 | /** Internal bind function for the IHTTPRequest::OnProcessRequestCompleted() event */ 165 | void OnProcessRequestComplete(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful); 166 | 167 | public: 168 | /** Event occured when the Request has been completed */ 169 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 170 | FOnRequestComplete OnRequestComplete; 171 | 172 | /** Event occured when the Request wasn't successfull */ 173 | UPROPERTY(BlueprintAssignable, Category = "Stomt|Event") 174 | FOnRequestFail OnRequestFail; 175 | 176 | ////////////////////////////////////////////////////////////////////////// 177 | // Data 178 | public: 179 | /** Wether to use a static json string instead of JsonObjects */ 180 | void UseStaticJsonString(bool bNewUseStaticJsonString); 181 | 182 | void UseRequestLogging(bool bNewRequestLogging); 183 | 184 | void SetStaticJsonString(FString JsonString); 185 | 186 | /** Request response stored as a string */ 187 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "StomtRest|Response") 188 | FString ResponseContent; 189 | 190 | /** Is the response valid JSON? */ 191 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "StomtRest|Response") 192 | bool bIsValidJsonResponse; 193 | 194 | protected: 195 | 196 | /** Wether to use a static json string instead of JsonObjects */ 197 | bool bUseStaticJsonString; 198 | 199 | /** Wether to use a log output for the Request */ 200 | bool bRequestLogging; 201 | 202 | /** Static json string that will be used instead of json objects */ 203 | FString StaticJsonOutputString; 204 | 205 | /** Latent action helper */ 206 | StomtLatentAction *ContinueAction; 207 | 208 | /** Internal Request data stored as JSON */ 209 | UPROPERTY() 210 | UStomtRestJsonObject* RequestJsonObj; 211 | 212 | /** Response data stored as JSON */ 213 | UPROPERTY() 214 | UStomtRestJsonObject* ResponseJsonObj; 215 | 216 | /** Verb for making Request (GET,POST,etc) */ 217 | StomtEnumRequestVerb::Type RequestVerb; 218 | 219 | /** Mapping of header section to values. Used to generate final header string for Request */ 220 | TMap RequestHeaders; 221 | 222 | /** Cached key/value header pairs. Parsed once Request completes */ 223 | TMap ResponseHeaders; 224 | 225 | /** Http Response code */ 226 | int32 ResponseCode; 227 | 228 | }; 229 | -------------------------------------------------------------------------------- /Source/StomtPlugin/Public/StomtTrack.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stomt/stomt-unreal-plugin/804051d511c93f424f8b5ea3ed24133109847917/Source/StomtPlugin/Public/StomtTrack.h -------------------------------------------------------------------------------- /Source/StomtPlugin/StomtPlugin.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 STOMT GmbH. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.IO; 5 | 6 | public class StomtPlugin : ModuleRules 7 | { 8 | public StomtPlugin(ReadOnlyTargetRules ROTargetRules) : base(ROTargetRules) 9 | { 10 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 11 | 12 | PrivateIncludePaths.AddRange(new string[] { "StomtPlugin/Private" }); 13 | PublicIncludePaths.AddRange(new string[] { "StomtPlugin/Public" }); 14 | 15 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HTTP", "Json", "UMG", "Slate", "SlateCore", "ImageWrapper" }); 16 | PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore", "UMG" }); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /StomtPlugin.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "Version": 10, 4 | "VersionName": "2.5.1", 5 | "EngineVersion" : "4.20.0", 6 | "FriendlyName": "StomtPlugin", 7 | "Description": "This Widget allows the easy integration of the feedback solution www.stomt.com in your game.", 8 | "Category": "Widgets", 9 | "CreatedBy": "STOMT", 10 | "CreatedByURL": "https://www.stomt.com", 11 | "DocsURL": "https://github.com/stomt/stomt-unreal-plugin", 12 | "MarketplaceURL" : "com.epicgames.launcher://ue/marketplace/content/7980672d57664bb5a567ff39f5106af6", 13 | "SupportURL": "https://www.stomt.com/stomt-unreal-engine-plugin", 14 | "CanContainContent": true, 15 | "IsBetaVersion": false, 16 | "Installed": false, 17 | "Modules": [ 18 | { 19 | "Name": "StomtPlugin", 20 | "Type": "Runtime", 21 | "LoadingPhase": "Default" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /pack.sh: -------------------------------------------------------------------------------- 1 | # RESET 2 | git add . 3 | git stash 4 | git checkout master 5 | 6 | 7 | # next (4.20) 8 | git add . 9 | git stash 10 | git checkout UE/4.20 11 | 12 | # move root files 13 | mv README.md Docs/README.md 14 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 15 | 16 | # zip 17 | rm ../stomt-unreal-plugin-4-20.zip 18 | zip -r -X ../stomt-unreal-plugin-4-20.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 19 | 20 | 21 | # next (4.21) 22 | git add . 23 | git stash 24 | git checkout UE/4.21 25 | 26 | # move root files 27 | mv README.md Docs/README.md 28 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 29 | 30 | # zip 31 | rm ../stomt-unreal-plugin-4-21.zip 32 | zip -r -X ../stomt-unreal-plugin-4-21.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 33 | 34 | 35 | # next (4.22) 36 | git add . 37 | git stash 38 | git checkout UE/4.22 39 | 40 | # move root files 41 | mv README.md Docs/README.md 42 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 43 | 44 | # zip 45 | rm ../stomt-unreal-plugin-4-22.zip 46 | zip -r -X ../stomt-unreal-plugin-4-22.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 47 | 48 | 49 | # next (4.23) 50 | git add . 51 | git stash 52 | git checkout UE/4.23 53 | 54 | # move root files 55 | mv README.md Docs/README.md 56 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 57 | 58 | # zip 59 | rm ../stomt-unreal-plugin-4-23.zip 60 | zip -r -X ../stomt-unreal-plugin-4-23.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 61 | 62 | 63 | # next (4.24) 64 | git add . 65 | git stash 66 | git checkout UE/4.24 67 | 68 | # move root files 69 | mv README.md Docs/README.md 70 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 71 | 72 | # zip 73 | rm ../stomt-unreal-plugin-4-24.zip 74 | zip -r -X ../stomt-unreal-plugin-4-24.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 75 | 76 | 77 | # next (4.25) 78 | git add . 79 | git stash 80 | git checkout UE/4.25 81 | 82 | # move root files 83 | mv README.md Docs/README.md 84 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 85 | 86 | # zip 87 | rm ../stomt-unreal-plugin-4-25.zip 88 | zip -r -X ../stomt-unreal-plugin-4-25.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 89 | 90 | 91 | # next (4.26) 92 | git add . 93 | git stash 94 | git checkout UE/4.26 95 | 96 | # move root files 97 | mv README.md Docs/README.md 98 | mv CONTRIBUTING.md Docs/CONTRIBUTING.md 99 | 100 | # zip 101 | rm ../stomt-unreal-plugin-4-26.zip 102 | zip -r -X ../stomt-unreal-plugin-4-26.zip . -x *.git* -x pack.sh -x scripts/ -x *.DS_Store* -x LICENSE.md -x Binaries/ -x Intermediate/ -x Binaries/**\* -x Intermediate/**\* 103 | 104 | 105 | ## FINSIH 106 | # clean 107 | git add . 108 | git stash 109 | git checkout master 110 | -------------------------------------------------------------------------------- /scripts/delete_branches.sh: -------------------------------------------------------------------------------- 1 | # RESET 2 | git add . 3 | git stash 4 | git checkout master 5 | 6 | 7 | # remove local braches (to remove changes in them) 8 | git branch -D UE/4.20 9 | git branch -D UE/4.21 10 | git branch -D UE/4.22 11 | git branch -D UE/4.23 12 | git branch -D UE/4.24 13 | git branch -D UE/4.25 14 | git branch -D UE/4.26 15 | -------------------------------------------------------------------------------- /scripts/push_branches.sh: -------------------------------------------------------------------------------- 1 | # RESET 2 | git add . 3 | git stash 4 | git checkout master 5 | 6 | # push tags 7 | git push --tags 8 | 9 | # push all updates 10 | git push origin master \ 11 | UE/4.20 \ 12 | UE/4.21 \ 13 | UE/4.22 \ 14 | UE/4.23 \ 15 | UE/4.24 \ 16 | UE/4.25 \ 17 | UE/4.26 \ 18 | 19 | -------------------------------------------------------------------------------- /scripts/update_branches.sh: -------------------------------------------------------------------------------- 1 | # RESET 2 | git add . 3 | git stash 4 | git checkout master 5 | 6 | 7 | # UE/4.20 8 | git checkout UE/4.20 9 | git merge master 10 | 11 | # UE/4.21 12 | git checkout UE/4.21 13 | git merge master 14 | 15 | # UE/4.22 16 | git checkout UE/4.22 17 | git merge master 18 | 19 | # UE/4.23 20 | git checkout UE/4.23 21 | git merge master 22 | 23 | # UE/4.24 24 | git checkout UE/4.24 25 | git merge master 26 | 27 | # UE/4.25 28 | git checkout UE/4.25 29 | git merge master 30 | 31 | # UE/4.26 32 | git checkout UE/4.26 33 | git merge master 34 | 35 | 36 | ## FINISH 37 | git checkout master 38 | --------------------------------------------------------------------------------