├── .gitignore ├── 3d ├── fshader.glsl └── vshader.glsl ├── Info.plist ├── JavascriptTextureGenerators └── lines.js ├── LICENSE ├── ProceduralTextureMaker.pro ├── README.md ├── base ├── settingsmanager.cpp ├── settingsmanager.h ├── textureimage.cpp ├── textureimage.h ├── texturenode.cpp ├── texturenode.h ├── textureproject.cpp ├── textureproject.h ├── texturerenderthread.cpp └── texturerenderthread.h ├── examples ├── rose.txl └── wall.txl ├── generators ├── blending.cpp ├── blending.h ├── boxblur.cpp ├── boxblur.h ├── bricks.cpp ├── bricks.h ├── checkboard.cpp ├── checkboard.h ├── circle.cpp ├── circle.h ├── cutout.cpp ├── cutout.h ├── displacementmap.cpp ├── displacementmap.h ├── empty.cpp ├── empty.h ├── fill.cpp ├── fill.h ├── fire.cpp ├── fire.h ├── gaussianblur.cpp ├── gaussianblur.h ├── glow.cpp ├── glow.h ├── gradient.cpp ├── gradient.h ├── greyscale.cpp ├── greyscale.h ├── invert.cpp ├── invert.h ├── javascript.cpp ├── javascript.h ├── lens.cpp ├── lens.h ├── lines.cpp ├── lines.h ├── merge.cpp ├── merge.h ├── mirror.cpp ├── mirror.h ├── modifylevels.cpp ├── modifylevels.h ├── noise.cpp ├── noise.h ├── normalmap.cpp ├── normalmap.h ├── perlinnoise.cpp ├── perlinnoise.h ├── pixelate.cpp ├── pixelate.h ├── pointillism.cpp ├── pointillism.h ├── setchannels.cpp ├── setchannels.h ├── shadow.cpp ├── shadow.h ├── sineplasma.cpp ├── sineplasma.h ├── sinetransform.cpp ├── sinetransform.h ├── square.cpp ├── square.h ├── stackblur.cpp ├── stackblur.h ├── star.cpp ├── star.h ├── text.cpp ├── text.h ├── texturegenerator.cpp ├── texturegenerator.h ├── transform.cpp ├── transform.h ├── whirl.cpp └── whirl.h ├── global.h ├── gui ├── addnodepanel.cpp ├── addnodepanel.h ├── connectionwidget.cpp ├── connectionwidget.h ├── cubewidget.cpp ├── cubewidget.h ├── iteminfopanel.cpp ├── iteminfopanel.h ├── mainwindow.cpp ├── mainwindow.h ├── menuactions.cpp ├── menuactions.h ├── nodesettingswidget.cpp ├── nodesettingswidget.h ├── previewimagepanel.cpp ├── previewimagepanel.h ├── qdoubleslider.h ├── sceneinfowidget.cpp ├── sceneinfowidget.h ├── settingspanel.cpp └── settingspanel.h ├── images ├── copyicon.png ├── cuticon.png ├── mainicon.icns ├── mainicon.ico ├── mainicon.png ├── new.png ├── open.png ├── pasteicon.png └── save.png ├── main.cpp ├── sceneview ├── viewnodeitem.cpp ├── viewnodeitem.h ├── viewnodeline.cpp ├── viewnodeline.h ├── viewnodescene.cpp ├── viewnodescene.h ├── viewnodeview.cpp └── viewnodeview.h ├── shaders.qrc ├── texgen.qrc ├── texgenapplication.cpp └── texgenapplication.h /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | 3 | *.slo 4 | *.lo 5 | *.o 6 | *.a 7 | *.la 8 | *.lai 9 | *.so 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | 15 | /.qmake.cache 16 | /.qmake.stash 17 | *.pro.user 18 | *.pro.user.* 19 | *.qbs.user 20 | *.qbs.user.* 21 | *.moc 22 | moc_*.cpp 23 | moc_*.h 24 | qrc_*.cpp 25 | ui_*.h 26 | Makefile* 27 | *build-* 28 | 29 | # QtCreator 30 | 31 | *.autosave 32 | 33 | # QtCtreator Qml 34 | *.qmlproject.user 35 | *.qmlproject.user.* 36 | 37 | # QtCtreator CMake 38 | CMakeLists.txt.user* 39 | 40 | /debug 41 | /release 42 | 43 | .DS_store 44 | *~ 45 | *.rc 46 | *plugin_import.cpp 47 | 48 | ProceduralTextureMaker -------------------------------------------------------------------------------- /3d/fshader.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | // Set default precision to medium 3 | precision mediump int; 4 | precision mediump float; 5 | #endif 6 | 7 | uniform sampler2D texture; 8 | varying vec2 v_texcoord; 9 | 10 | void main() 11 | { 12 | // Set fragment color from texture 13 | gl_FragColor = texture2D(texture, v_texcoord); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /3d/vshader.glsl: -------------------------------------------------------------------------------- 1 | #ifdef GL_ES 2 | // Set default precision to medium 3 | precision mediump int; 4 | precision mediump float; 5 | #endif 6 | 7 | uniform mat4 mvp_matrix; 8 | attribute vec4 a_position; 9 | attribute vec2 a_texcoord; 10 | varying vec2 v_texcoord; 11 | 12 | void main() 13 | { 14 | // Calculate vertex position in screen space 15 | gl_Position = mvp_matrix * a_position; 16 | // Pass texture coordinate to fragment shader 17 | // Value will be automatically interpolated to fragments inside polygon faces 18 | v_texcoord = a_texcoord; 19 | } 20 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrincipalClass 6 | NSApplication 7 | CFBundleIconFile 8 | mainicon.icns 9 | CFBundlePackageType 10 | APPL 11 | CFBundleGetInfoString 12 | ProceduralTextureMaker 13 | CFBundleSignature 14 | ???? 15 | CFBundleExecutable 16 | ProceduralTextureMaker 17 | CFBundleIdentifier 18 | com.github.johanokl.ProceduralTextureMaker 19 | NOTE 20 | Don't edit 21 | CFBundleDocumentTypes 22 | 23 | 24 | CFBundleTypeExtensions 25 | 26 | txl 27 | 28 | CFBundleTypeRole 29 | Editor 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /JavascriptTextureGenerators/lines.js: -------------------------------------------------------------------------------- 1 | var name = "LinesJS"; 2 | var numSlots = 1; 3 | // Set separateColorChannels to true to have one array index per color 4 | // If set to false all four channels are interleaved in one 32 bit value. 5 | var separateColorChannels = false; 6 | 7 | function generate(data, sourceImg) { 8 | var obj = JSON.parse(data); 9 | var color = obj.color.a + 10 | (obj.color.b << 8) + 11 | (obj.color.g << 16) + 12 | (obj.color.r << 24); 13 | obj.imagewidth = parseInt(obj.imagewidth); 14 | obj.imageheight = parseInt(obj.imageheight); 15 | obj.distance = Math.round(obj.distance * obj.imageheight / 100); 16 | obj.height = Math.round(obj.height * obj.imageheight / 100); 17 | obj.offset = Math.round(obj.offset * obj.imageheight / 100); 18 | 19 | if (obj.imageheight > 0) { 20 | var x, y; 21 | for (y = 0; y < obj.imageheight; y++) { 22 | var linestart = y * obj.imagewidth; 23 | if (((y + obj.offset) % (obj.height + obj.distance)) > obj.distance) { 24 | for (x = 0; x < obj.imagewidth; x++) { 25 | dest[linestart + x] = color; 26 | } 27 | } else if (sourceImg) { 28 | for (x = 0; x < obj.imagewidth; x++) { 29 | dest[linestart + x] = sourceImg[linestart + x]; 30 | } 31 | } else { 32 | for (x = 0; x < obj.imagewidth; x++) { 33 | dest[linestart + x] = 0; 34 | } 35 | } 36 | } 37 | } 38 | return dest; 39 | } 40 | 41 | function getSettings() { 42 | return { 43 | color: { 44 | name: "Line color", 45 | defaultvalue: { 46 | r: 255, 47 | g: 100, 48 | b: 50, 49 | a: 255 50 | }, 51 | type: "color", 52 | order: 1 53 | }, 54 | height: { 55 | name: "Line height", 56 | defaultvalue: 10, 57 | min: 0, 58 | max: 100, 59 | type: "integer", 60 | order: 2 61 | }, 62 | distance: { 63 | name: "Distance", 64 | defaultvalue: 10, 65 | min: 0, 66 | max: 100, 67 | type: "integer", 68 | order: 3 69 | }, 70 | offset: { 71 | name: "Offset", 72 | defaultvalue: 0, 73 | min: 0, 74 | max: 100, 75 | type: "integer", 76 | order: 4 77 | } 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /ProceduralTextureMaker.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = "ProceduralTextureMaker" 3 | 4 | macx { 5 | # Possible to include spaces in the file name if on Mac OS X. 6 | TARGET = "ProceduralTextureMaker" 7 | QMAKE_MAC_SDK = 10.13 8 | QMAKE_INFO_PLIST += Info.plist 9 | OTHER_FILES += Info.plist 10 | } 11 | 12 | # Select which Javascript engine to include 13 | # ----------------------------------------- 14 | # Qt's QScriptEngine is deprecated and might be removed 15 | # while QJSEngine (in Qt 5.9 and 5.10) still has some 16 | # strange bugs releated to memory management. 17 | # Uncomment the line "#defines USE_QJSENGINE" below if QtScript isn't 18 | # available or QJSEngine is stable and enough to be a viable alternative. 19 | # For QScriptEngine, remember to also include module script. 20 | # For QJSEngine, remember to also include module qml. 21 | # It is also possible to disable Javascript support, if both 22 | # QML/QJSEngine and QtScript/QScriptEngine are missing from the system. 23 | # To do so, uncomment the line "#defines DISABLE_JAVASCRIPT". 24 | # ----------------------------------------- 25 | #DEFINES += "DISABLE_JAVASCRIPT" 26 | 27 | qtHaveModule(qml) { 28 | QT += qml 29 | DEFINES += "USE_QJSENGINE" 30 | } 31 | else { qtHaveModule(script) { 32 | QT += script 33 | } 34 | else { 35 | DEFINES += "DISABLE_JAVASCRIPT" 36 | }} 37 | 38 | QT += xml \ 39 | widgets \ 40 | gui \ 41 | core 42 | 43 | CONFIG += c++11 44 | 45 | INCLUDEPATH += src 46 | 47 | SOURCES = \ 48 | main.cpp \ 49 | texgenapplication.cpp \ 50 | base/texturenode.cpp \ 51 | base/textureimage.cpp \ 52 | base/texturerenderthread.cpp \ 53 | base/settingsmanager.cpp \ 54 | base/textureproject.cpp \ 55 | gui/nodesettingswidget.cpp \ 56 | gui/mainwindow.cpp \ 57 | gui/addnodepanel.cpp \ 58 | gui/settingspanel.cpp \ 59 | gui/menuactions.cpp \ 60 | gui/connectionwidget.cpp \ 61 | gui/sceneinfowidget.cpp \ 62 | gui/iteminfopanel.cpp \ 63 | gui/previewimagepanel.cpp \ 64 | gui/cubewidget.cpp \ 65 | sceneview/viewnodeview.cpp \ 66 | sceneview/viewnodeitem.cpp \ 67 | sceneview/viewnodescene.cpp \ 68 | sceneview/viewnodeline.cpp \ 69 | generators/blending.cpp \ 70 | generators/boxblur.cpp \ 71 | generators/bricks.cpp \ 72 | generators/checkboard.cpp \ 73 | generators/circle.cpp \ 74 | generators/cutout.cpp \ 75 | generators/displacementmap.cpp \ 76 | generators/empty.cpp \ 77 | generators/fill.cpp \ 78 | generators/fire.cpp \ 79 | generators/gaussianblur.cpp \ 80 | generators/glow.cpp \ 81 | generators/greyscale.cpp \ 82 | generators/gradient.cpp \ 83 | generators/invert.cpp \ 84 | generators/javascript.cpp \ 85 | generators/lens.cpp \ 86 | generators/lines.cpp \ 87 | generators/mirror.cpp \ 88 | generators/merge.cpp \ 89 | generators/modifylevels.cpp \ 90 | generators/noise.cpp \ 91 | generators/normalmap.cpp \ 92 | generators/perlinnoise.cpp \ 93 | generators/pixelate.cpp \ 94 | generators/pointillism.cpp \ 95 | generators/shadow.cpp \ 96 | generators/sinetransform.cpp \ 97 | generators/sineplasma.cpp \ 98 | generators/stackblur.cpp \ 99 | generators/square.cpp \ 100 | generators/star.cpp \ 101 | generators/setchannels.cpp \ 102 | generators/texturegenerator.cpp \ 103 | generators/transform.cpp \ 104 | generators/text.cpp \ 105 | generators/whirl.cpp 106 | 107 | HEADERS += \ 108 | global.h \ 109 | texgenapplication.h \ 110 | base/texturenode.h \ 111 | base/textureimage.h \ 112 | base/texturerenderthread.h \ 113 | base/settingsmanager.h \ 114 | base/textureproject.h \ 115 | gui/addnodepanel.h \ 116 | gui/qdoubleslider.h \ 117 | gui/nodesettingswidget.h \ 118 | gui/settingspanel.h \ 119 | gui/mainwindow.h \ 120 | gui/menuactions.h \ 121 | gui/connectionwidget.h \ 122 | gui/sceneinfowidget.h \ 123 | gui/iteminfopanel.h \ 124 | gui/previewimagepanel.h \ 125 | gui/cubewidget.h \ 126 | sceneview/viewnodeitem.h \ 127 | sceneview/viewnodescene.h \ 128 | sceneview/viewnodeline.h \ 129 | sceneview/viewnodeview.h \ 130 | generators/texturegenerator.h \ 131 | generators/blending.h \ 132 | generators/bricks.h \ 133 | generators/boxblur.h \ 134 | generators/checkboard.h \ 135 | generators/cutout.h \ 136 | generators/circle.h \ 137 | generators/displacementmap.h \ 138 | generators/empty.h \ 139 | generators/fill.h \ 140 | generators/fire.h \ 141 | generators/gaussianblur.h \ 142 | generators/glow.h \ 143 | generators/gradient.h \ 144 | generators/greyscale.h \ 145 | generators/invert.h \ 146 | generators/javascript.h \ 147 | generators/lens.h \ 148 | generators/lines.h \ 149 | generators/merge.h \ 150 | generators/mirror.h \ 151 | generators/modifylevels.h \ 152 | generators/noise.h \ 153 | generators/normalmap.h \ 154 | generators/perlinnoise.h \ 155 | generators/pixelate.h \ 156 | generators/pointillism.h \ 157 | generators/shadow.h \ 158 | generators/sineplasma.h \ 159 | generators/sinetransform.h \ 160 | generators/setchannels.h \ 161 | generators/square.h \ 162 | generators/stackblur.h \ 163 | generators/star.h \ 164 | generators/text.h \ 165 | generators/transform.h \ 166 | generators/whirl.h 167 | 168 | RESOURCES += \ 169 | texgen.qrc \ 170 | shaders.qrc 171 | 172 | RC_ICONS += images/mainicon.ico 173 | ICON += images/mainicon.icns 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ProceduralTextureMaker 2 | ======================== 3 | 4 | ### Introduction 5 | ProceduralTextureMaker generates texture images in arbitrary sizes based on graphs of nodes that take other nodes' output as input and transform them into new images. 6 | 7 | Nodes are added dynamically and connected to each other graphically. 8 | Custom UI widgets are created for each node based on the texture generator's user configurable settings, making it easy to try out new configurations and watch how changes affect the final output. 9 | The project files with texture graphs can be saved to and loaded from XML files, and images can be exported to PNG files. 10 | 11 | A number of texture generators written in C++ and Javascript are included with the project. 12 | 13 | For more general information about procedural textures, see https://en.wikipedia.org/wiki/Procedural_texture 14 | 15 | ### Screenshot 16 | ![Screenshot 1](https://i.imgur.com/Ikn4oLt.png) 17 | 18 | ### Examples 19 | Two example textures have been added to the repository: 20 | * [Rose](examples/rose.txl) 21 | * [Wall](examples/wall.txl) 22 | 23 | ### Technical Details 24 | The application is written in C++ and uses the Qt framework. 25 | It has been tested with Qt versions 5.9, 5.10, 5.12 and 5.15 on Mac OS, Ubuntu and Windows 10. 26 | It uses multiple threads on multiple CPU cores where supported, so that CPU intensive texture calculations don't affect the UI performance. 27 | It's easy to extend the application by adding new generators, especially ones written in Javacript as those are loaded dynamically from external files. 28 | 29 | ### Javascript 30 | One example Javascript texture generator is included in the directory _JavascriptTextureGenerators_. 31 | The external Javascript texture generators are parsed and run using the QtScript engine. 32 | As the QtScript module is listed as deprecated and not installed by default by the Qt installer there is also support for running the scripts with the newer QJSEngine class. 33 | QScriptEngine and not QJSEngine is still enabled by default as there were some strange unresolved bugs related to QJSEngine version 5.10's memory management encountered during development. 34 | Changing which engine that should be used is done by adding or removing `DEFINES += "USE_QJSENGINE"` in _ProceduralTextureMaker.pro_. 35 | 36 | ### How to build 37 | Install and configure Qt 5.15, available at https://www.qt.io/download-open-source 38 | If you're compiling with the QScript engine (see the Javascript section above) make sure that the Qt installation includes that module. 39 | If Qt Creator was installed, use it to open and build the project file `ProceduralTextureMaker.pro`. 40 | If Qt Creator isn't available, use a terminal to browse to the project root directory and run `qmake && make && make install`. 41 | 42 | ### License 43 | Released under GPL version 3. 44 | 45 | ### Author 46 | Johan Lindqvist 47 | johan.lindqvist@gmail.com 48 | https://github.com/johanokl 49 | 50 | Icon from https://www.iconfinder.com/icons/28730/ 51 | -------------------------------------------------------------------------------- /base/settingsmanager.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SETTINGSMANAGER_H 9 | #define SETTINGSMANAGER_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * @brief The SettingsManager class 17 | * 18 | * Manages the global settings. Settings are written to 19 | * and loaded from persistent storage using the QSettings class. 20 | */ 21 | class SettingsManager : public QObject 22 | { 23 | Q_OBJECT 24 | 25 | public: 26 | SettingsManager() = default; 27 | ~SettingsManager() override = default; 28 | QSize getPreviewSize() const; 29 | QSize getThumbnailSize() const; 30 | QString getJSTextureGeneratorsPath() const; 31 | bool getJSTextureGeneratorsEnabled() const; 32 | QColor getPreviewBackgroundColor() const; 33 | QColor getBackgroundColor() const; 34 | int getBackgroundBrush() const; 35 | int getDefaultZoom() const; 36 | 37 | signals: 38 | void settingsUpdated(); 39 | 40 | public slots: 41 | void setDefaultZoom(int); 42 | void setPreviewSize(const QSize&); 43 | void setThumbnailSize(const QSize&); 44 | void setPreviewBackgroundColor(const QColor&); 45 | void setBackgroundColor(const QColor&); 46 | void setBackgroundBrush(int val); 47 | void setJSTextureGeneratorsPath(const QString&); 48 | void setJSTextureGeneratorsEnabled(bool); 49 | }; 50 | 51 | #endif // SETTINGSMANAGER_H 52 | -------------------------------------------------------------------------------- /base/textureimage.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "textureimage.h" 9 | #include 10 | #include 11 | 12 | /** 13 | * @brief TextureImage::TextureImage 14 | * @param size Image pixel dimensions 15 | * @param data TexturePixels, size must be at least width*height 16 | */ 17 | TextureImage::TextureImage(QSize size, TexturePixel* data) 18 | { 19 | this->size = size; 20 | this->data = data; 21 | } 22 | 23 | /** 24 | * @brief TextureImage::~TextureImage 25 | */ 26 | TextureImage::~TextureImage() 27 | { 28 | if (data != nullptr) { 29 | delete data; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /base/textureimage.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTUREIMAGE_H 9 | #define TEXTUREIMAGE_H 10 | 11 | #include "global.h" 12 | #include 13 | #include 14 | 15 | /** 16 | * @brief The TextureImage class 17 | * 18 | * Holds the data for an image 19 | */ 20 | class TextureImage 21 | { 22 | public: 23 | TextureImage(QSize size, TexturePixel* data); 24 | virtual ~TextureImage(); 25 | QSize getSize() const { return size; } 26 | TexturePixel* getData() const { return data; } 27 | 28 | private: 29 | QSize size; 30 | TexturePixel* data; 31 | }; 32 | 33 | /** 34 | * @brief TextureImagePtr 35 | * 36 | * Thread-safe smart pointer for TextureImage 37 | */ 38 | using TextureImagePtr = QSharedPointer; 39 | 40 | 41 | #endif // TEXTUREIMAGE_H 42 | -------------------------------------------------------------------------------- /base/texturenode.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTURENODE_H 9 | #define TEXTURENODE_H 10 | 11 | #include "generators/texturegenerator.h" 12 | #include "global.h" 13 | #include "textureimage.h" 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | class TextureProject; 21 | class TextureNode; 22 | 23 | /** 24 | * @brief TextureNodePtr 25 | * Thread-safe smart pointer for TextureNode objects. 26 | */ 27 | using TextureNodePtr = QSharedPointer; 28 | 29 | /** 30 | * @brief The TextureNode class 31 | * 32 | * A node in the graph with its settings, attributes 33 | * and links to its source and receiver nodes. 34 | */ 35 | class TextureNode : public QObject 36 | { 37 | Q_OBJECT 38 | friend class TextureProject; 39 | 40 | public: 41 | ~TextureNode() override; 42 | void release(); 43 | int getId() const { return id; } 44 | QString getName() const { return name; } 45 | void setName(const QString& name); 46 | bool setGenerator(const QString& name); 47 | bool setGenerator(TextureGeneratorPtr gen); 48 | TextureGeneratorPtr getGenerator() const { return gen; } 49 | QString getGeneratorName() const; 50 | int getNumSourceSlots() const; 51 | int getNumReceivers() const { return receivers.size(); } 52 | QSetIterator getReceivers() const { return QSetIterator(receivers); } 53 | bool slotAvailable(int slot) const; 54 | bool setSourceSlot(int slot, int value); 55 | bool findLoop() const; 56 | QPointF getPos() const { return pos; } 57 | void setPos(QPointF pos); 58 | TextureImagePtr getImage(QSize size); 59 | void setUpdated(); 60 | bool isTextureInCache(QSize size) const; 61 | int waitingFor(QSize size) const; 62 | const TextureNodeSettings getSettings() const { return settings; } 63 | void setSettings(const TextureNodeSettings& settings); 64 | const QMap getSources() const { return sources; } 65 | 66 | signals: 67 | void positionUpdated(int id); 68 | void imageUpdated(int id); 69 | void slotsUpdated(int id); 70 | void imageAvailable(int id, QSize size); 71 | void settingsUpdated(int id); 72 | void generatorUpdated(int id); 73 | void nodesConnected(int sourceId, int receiverId, int slot); 74 | void nodesDisconnected(int sourceId, int receiverId, int slot); 75 | 76 | private: 77 | TextureNode(TextureProject* project, const TextureGeneratorPtr& generator, int id); 78 | void loadFromXML(const QDomNode& xmlnode, const QMap idMapping = QMap()); 79 | QDomElement saveAsXML(QDomDocument targetdoc); 80 | bool findLoop(QList visited) const; 81 | void removeSource(int id); 82 | 83 | int id; 84 | QString name; 85 | QPointF pos; 86 | 87 | QMap sources; 88 | QSet receivers; 89 | TextureNodeSettings settings; 90 | 91 | TextureGeneratorPtr gen; 92 | TextureProject* project; 93 | 94 | // Contains all the generated images 95 | QMap texturecache; 96 | // Set to true after releasing all connections, before delete 97 | bool deleted; 98 | QMap validImage; 99 | 100 | // Mutexes to make it thread-safe. 101 | mutable QReadWriteLock sourcemutex; 102 | mutable QReadWriteLock receivermutex; 103 | mutable QReadWriteLock imagemutex; 104 | mutable QReadWriteLock settingsmutex; 105 | }; 106 | 107 | #endif // TEXTURENODE_H 108 | -------------------------------------------------------------------------------- /base/textureproject.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTUREPROJECT_H 9 | #define TEXTUREPROJECT_H 10 | 11 | #include "texturenode.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | class TextureRenderThread; 19 | class TextureGenerator; 20 | class SettingsManager; 21 | 22 | /** 23 | * @brief The TextureProject class 24 | * 25 | * Manages all the texture generators, TextureNode instances and 26 | * the connections between them. 27 | */ 28 | class TextureProject : public QObject 29 | { 30 | Q_OBJECT 31 | friend class TextureNode; 32 | 33 | public: 34 | TextureProject(); 35 | ~TextureProject() override; 36 | QDomDocument saveAsXML(bool includegenerators = false); 37 | void loadFromXML(const QDomDocument& xmlfile); 38 | QString getName() const { return name; } 39 | void setName(const QString&); 40 | TextureNodePtr getNode(int id) const; 41 | bool findLoops() const; 42 | void removeNode(int id); 43 | TextureNodePtr newNode(int id = 0, TextureGeneratorPtr generator = TextureGeneratorPtr(nullptr)); 44 | void clear(); 45 | bool isModified() const; 46 | int getNumNodes() const; 47 | TextureGeneratorPtr getGenerator(const QString& name) const; 48 | QMap getGenerators() const { return generators; } 49 | QSize getThumbnailSize() const { return thumbnailSize; } 50 | QSize getPreviewSize() const { return previewSize; } 51 | void setSettingsManager(SettingsManager* manager); 52 | SettingsManager* getSettingsManager() const { return settingsManager; } 53 | 54 | public slots: 55 | void addGenerator(const TextureGeneratorPtr& gen); 56 | void removeGenerator(const TextureGeneratorPtr& gen); 57 | void notifyNodesConnected(int sourceId, int receiverId, int slot); 58 | void notifyNodesDisconnected(int sourceId, int receiverId, int slot); 59 | void notifyImageUpdated(int id); 60 | void notifyImageAvailable(int id, QSize size); 61 | void copyNode(int id); 62 | void cutNode(int id); 63 | void pasteNode(); 64 | void settingsUpdated(); 65 | 66 | signals: 67 | void nodeAdded(TextureNodePtr); 68 | void nodeRemoved(int); 69 | void nodesConnected(int, int, int); 70 | void nodesDisconnected(int, int, int); 71 | void imageUpdated(int); 72 | void imageAvailable(int, QSize); 73 | void nameUpdated(QString); 74 | void generatorAdded(TextureGeneratorPtr); 75 | void generatorRemoved(TextureGeneratorPtr); 76 | void generatorNameCollision(TextureGeneratorPtr, TextureGeneratorPtr); 77 | 78 | private: 79 | TextureGeneratorPtr getEmptyGenerator() const { return emptygenerator; } 80 | void startRenderThread(QSize renderSize, QThread::Priority = QThread::NormalPriority); 81 | void stopRenderThread(QSize renderSize); 82 | int getNewId(); 83 | 84 | QString name; 85 | int newIdCounter; 86 | TextureGeneratorPtr emptygenerator; 87 | QMap renderThreads; 88 | QMap nodes; 89 | QMap generators; 90 | mutable QReadWriteLock nodesmutex; 91 | 92 | QSize thumbnailSize; 93 | QSize previewSize; 94 | SettingsManager* settingsManager; 95 | bool modified; 96 | }; 97 | 98 | #endif // TEXTUREPROJECT_H 99 | -------------------------------------------------------------------------------- /base/texturerenderthread.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * Part of the ProceduralTextureMaker project. 5 | * http://github.com/johanokl/ProceduralTextureMaker 6 | * Released under GPLv3. 7 | * Johan Lindqvist (johan.lindqvist@gmail.com) 8 | */ 9 | 10 | #include "texturerenderthread.h" 11 | #include "global.h" 12 | #include "texturenode.h" 13 | 14 | /** 15 | * @brief TextureRenderThread::TextureRenderThread 16 | * @param renderSize Static rendersize. 17 | * @param nodes 18 | */ 19 | TextureRenderThread::TextureRenderThread(const QSize inRendersize, QMap inNodesMap) 20 | : renderSize(inRendersize), nodes(std::move(inNodesMap)) 21 | { 22 | aborted = false; 23 | } 24 | 25 | /** 26 | * @brief TextureRenderThread::abort 27 | * 28 | * Stops a thread from rendering more images. 29 | * Finishes the current one and then stops. 30 | */ 31 | void TextureRenderThread::abort() 32 | { 33 | aborted = true; 34 | } 35 | 36 | /** 37 | * @brief TextureRenderThread::generate 38 | * 39 | * Loops through the node list and generates images until all nodes 40 | * have an image this thread's image size in their cache. 41 | */ 42 | void TextureRenderThread::generate() 43 | { 44 | bool someGenerated; 45 | do { 46 | someGenerated = false; 47 | QMapIterator nodeIterator(nodes); 48 | while (!aborted && nodeIterator.hasNext()) { 49 | TextureNodePtr currNode = nodeIterator.next().value(); 50 | if (currNode->waitingFor(renderSize) == 0 51 | && !currNode->isTextureInCache(renderSize)) { 52 | currNode->getImage(renderSize); 53 | someGenerated = true; 54 | } 55 | } 56 | } while (!aborted && someGenerated); 57 | } 58 | 59 | /** 60 | * @brief TextureRenderThread::imageUpdated 61 | * @param id Node id. 62 | * 63 | * Callback function for when a node has been updated 64 | * and a new image needs to be rendered for it. 65 | */ 66 | void TextureRenderThread::imageUpdated() 67 | { 68 | generate(); 69 | } 70 | 71 | /** 72 | * @brief TextureRenderThread::nodeAdded 73 | * @param newNode 74 | * 75 | * Adds a node to the internal node list. 76 | */ 77 | void TextureRenderThread::nodeAdded(const TextureNodePtr& newNode) 78 | { 79 | if (!nodes.contains(newNode->getId())) { 80 | nodes.insert(newNode->getId(), newNode); 81 | generate(); 82 | } 83 | } 84 | 85 | /** 86 | * @brief TextureRenderThread::nodeRemoved 87 | * @param id Node id 88 | * 89 | * Removes a node from the internal node list, thus no longer 90 | * rendering images for that node. 91 | */ 92 | void TextureRenderThread::nodeRemoved(int id) 93 | { 94 | if (nodes.contains(id)) { 95 | nodes.remove(id); 96 | generate(); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /base/texturerenderthread.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTURERENDERTHREAD_H 9 | #define TEXTURERENDERTHREAD_H 10 | 11 | #include "texturenode.h" 12 | #include 13 | 14 | class TextureProject; 15 | 16 | /** 17 | * @brief The TextureRenderThread class 18 | * 19 | * Class for moving the image rendering to a separate CPU thread. 20 | * Stays idle when no image needs to be generated. 21 | * One thread only handles one image size, so create one instance for each size. 22 | */ 23 | class TextureRenderThread : public QObject 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | TextureRenderThread(const QSize renderSize, QMap nodes); 29 | ~TextureRenderThread() override = default; 30 | void abort(); 31 | 32 | public slots: 33 | void imageUpdated(); 34 | void nodeRemoved(int remNode); 35 | void nodeAdded(const TextureNodePtr& newNode); 36 | 37 | private: 38 | void generate(); 39 | bool noneGenerated; 40 | const QSize renderSize; 41 | QMap nodes; 42 | bool aborted; 43 | }; 44 | 45 | #endif // TEXTURERENDERTHREAD_H 46 | -------------------------------------------------------------------------------- /generators/blending.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef BLENDINGTEXTUREGENERATOR_H 9 | #define BLENDINGTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The BlendingTextureGenerator class 15 | */ 16 | class BlendingTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | enum BlendModes { 20 | Normal = 1, 21 | Darken = 2, 22 | Multiply = 3, 23 | Lighten = 4, 24 | Screen = 5, 25 | ColorDodge = 6, 26 | ColorBurn = 7, 27 | Overlay = 8, 28 | SoftLight = 9, 29 | HardLight = 10, 30 | Difference = 11, 31 | Exclusion = 12 32 | }; 33 | 34 | BlendingTextureGenerator(); 35 | ~BlendingTextureGenerator() override = default; 36 | void generate(QSize size, 37 | TexturePixel* destimage, 38 | QMap sourceimages, 39 | TextureNodeSettings* settings) const override; 40 | int getNumSourceSlots() const override { return 2; } 41 | QString getName() const override { return QString("Blending"); } 42 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 43 | QString getDescription() const override { return QString("Blends two textures together."); } 44 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Combiner; } 45 | 46 | private: 47 | TextureGeneratorSettings configurables; 48 | double blendColors(BlendModes mode, double originColor, double addColor) const; 49 | int alphaCompose(double originAlpha, double addAlpha, double compositeAlpha, 50 | double originColor, double addColor, double compositeColor) const; 51 | }; 52 | 53 | #endif // BLENDINGTEXTUREGENERATOR_H 54 | 55 | 56 | -------------------------------------------------------------------------------- /generators/boxblur.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "boxblur.h" 9 | 10 | BoxBlurTextureGenerator::BoxBlurTextureGenerator() 11 | { 12 | TextureGeneratorSetting neighbourssetting; 13 | neighbourssetting.defaultvalue = QVariant((int) 5); 14 | neighbourssetting.name = "Blur level"; 15 | neighbourssetting.min = QVariant(0); 16 | neighbourssetting.max = QVariant(30); 17 | configurables.insert("numneighbours", neighbourssetting); 18 | } 19 | 20 | 21 | void BoxBlurTextureGenerator::generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const 25 | { 26 | if (!settings || !destimage || !size.isValid()) { 27 | return; 28 | } 29 | if (!sourceimages.contains(0)) { 30 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 31 | return; 32 | } 33 | TexturePixel* sourceImage = sourceimages.value(0).data()->getData(); 34 | if (settings->value("numneighbours").toInt() == 0) { 35 | memcpy(destimage, sourceImage, size.width() * size.height() * sizeof(TexturePixel)); 36 | return; 37 | } 38 | int numNeightboursX = settings->value("numneighbours").toDouble() * qMax(size.width() / 250, 1); 39 | int numNeightboursY = settings->value("numneighbours").toDouble() * qMax(size.height() / 250, 1); 40 | for (int j = 0; j < size.height(); j++) { 41 | for (int i = 0; i < size.width(); i++) { 42 | int startX = i - numNeightboursX; 43 | int endX = i + numNeightboursX; 44 | int startY = j - numNeightboursY; 45 | int endY = j + numNeightboursY; 46 | int totalPixels = 0; 47 | quint64 red = 0; 48 | quint64 green = 0; 49 | quint64 blue = 0; 50 | quint64 alpha = 0; 51 | for (int ypos = startY; ypos < endY; ypos++) { 52 | int currY = ypos; 53 | if (currY < 0) { 54 | currY += size.height() * 5; 55 | } 56 | currY %= size.height(); 57 | currY *= size.width(); 58 | for (int xpos = startX; xpos < endX; xpos++) { 59 | int currX = xpos; 60 | if (currX < 0) { 61 | currX += size.width() * 5; 62 | } 63 | currX %= size.width(); 64 | totalPixels++; 65 | TexturePixel sourcePixel = sourceImage[currY + currX]; 66 | red += sourcePixel.r; 67 | green += sourcePixel.g; 68 | blue += sourcePixel.b; 69 | alpha += sourcePixel.a; 70 | } 71 | } 72 | int pixelpos = j * size.width() + i; 73 | destimage[pixelpos].r = static_cast(red / totalPixels); 74 | destimage[pixelpos].g = static_cast(green / totalPixels); 75 | destimage[pixelpos].b = static_cast(blue / totalPixels); 76 | destimage[pixelpos].a = static_cast(alpha / totalPixels); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /generators/boxblur.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef BOXBLURTEXTUREGENERATOR_H 9 | #define BOXBLURTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The BoxBlurTextureGenerator class 15 | */ 16 | class BoxBlurTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | BoxBlurTextureGenerator(); 20 | ~BoxBlurTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Box blur"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // BOXBLURTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/bricks.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "bricks.h" 9 | #include 10 | #include 11 | 12 | BricksTextureGenerator::BricksTextureGenerator() 13 | { 14 | TextureGeneratorSetting color; 15 | color.name = "Color"; 16 | color.defaultvalue = QVariant(QColor(200, 200, 200, 255)); 17 | color.order = 1; 18 | configurables.insert("color", color); 19 | 20 | TextureGeneratorSetting linewidth; 21 | linewidth.name = "Line width"; 22 | linewidth.defaultvalue = QVariant((int) 10); 23 | linewidth.min = QVariant(0); 24 | linewidth.max = QVariant(100); 25 | linewidth.order = 2; 26 | configurables.insert("linewidth", linewidth); 27 | 28 | TextureGeneratorSetting brickwidth; 29 | brickwidth.name = "Brick width"; 30 | brickwidth.defaultvalue = QVariant((int) 120); 31 | brickwidth.min = QVariant(0); 32 | brickwidth.max = QVariant(300); 33 | brickwidth.group = "size"; 34 | brickwidth.order = 3; 35 | configurables.insert("brickwidth", brickwidth); 36 | 37 | TextureGeneratorSetting brickheight; 38 | brickheight.name = "Brick height"; 39 | brickheight.defaultvalue = QVariant((int) 45); 40 | brickheight.min = QVariant(0); 41 | brickheight.max = QVariant(300); 42 | brickheight.group = "size"; 43 | brickheight.order = 4; 44 | configurables.insert("brickheight", brickheight); 45 | 46 | TextureGeneratorSetting offsetx; 47 | offsetx.name = "Offset left"; 48 | offsetx.defaultvalue = QVariant((int) 0); 49 | offsetx.min = QVariant(-100); 50 | offsetx.max = QVariant(100); 51 | offsetx.order = 5; 52 | configurables.insert("offsetx", offsetx); 53 | 54 | TextureGeneratorSetting offsety; 55 | offsety.name = "Offset top"; 56 | offsety.defaultvalue = QVariant((int) 0); 57 | offsety.min = QVariant(-100); 58 | offsety.max = QVariant(100); 59 | offsety.order = 6; 60 | configurables.insert("offsety", offsety); 61 | } 62 | 63 | 64 | void BricksTextureGenerator::generate(QSize size, 65 | TexturePixel* destimage, 66 | QMap sourceimages, 67 | TextureNodeSettings* settings) const 68 | { 69 | if (!settings || !destimage || !size.isValid()) { 70 | return; 71 | } 72 | QColor color = settings->value("color").value(); 73 | int linewidth = settings->value("linewidth").toDouble() * size.height() / 300; 74 | int brickheight = settings->value("brickheight").toDouble() * size.height() / 300; 75 | int brickwidth = settings->value("brickwidth").toDouble() * size.width() / 300; 76 | int offsetx = settings->value("offsetx").toDouble() * size.width() / 100; 77 | int offsety = settings->value("offsety").toDouble() * size.height() / 100; 78 | 79 | if (sourceimages.contains(0)) { 80 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 81 | } else { 82 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 83 | } 84 | 85 | bool invert = false; 86 | QVector lines; 87 | 88 | int currY = offsety - size.height() - brickheight / 2; 89 | while (currY < (size.height() + linewidth / 2)) { 90 | if (currY > (-linewidth / 2) && currY < (size.height() + linewidth)) { 91 | lines.append(QLine(0, currY, size.width(), currY)); 92 | } 93 | invert = !invert; 94 | int currX = offsetx - size.width() - brickwidth / 2; 95 | if (invert) { 96 | currX += brickwidth / 2; 97 | } 98 | while (currX < (size.width() + linewidth / 2)) { 99 | if (currX > (-linewidth / 2) && currX < (size.width() + linewidth)) { 100 | lines.append(QLine(currX, currY, currX, currY + brickheight + linewidth)); 101 | } 102 | currX += brickwidth + linewidth; 103 | } 104 | currY += brickheight + linewidth; 105 | } 106 | QImage tempimage = QImage(size.width(), size.height(), QImage::Format_RGB32); 107 | memcpy(tempimage.bits(), destimage, size.width() * size.height() * sizeof(TexturePixel)); 108 | QPainter painter(&tempimage); 109 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 110 | painter.setBrush(QBrush(color, Qt::BrushStyle::SolidPattern)); 111 | painter.setPen(QPen(color, linewidth, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin)); 112 | painter.drawLines(lines); 113 | memcpy(destimage, tempimage.bits(), size.width() * size.height() * sizeof(TexturePixel)); 114 | } 115 | -------------------------------------------------------------------------------- /generators/bricks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef BRICKSTEXTUREGENERATOR_H 9 | #define BRICKSTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The BricksTextureGenerator class 15 | */ 16 | class BricksTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | BricksTextureGenerator(); 20 | ~BricksTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Bricks"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws rectangle bricks"); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // BRICKSTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/checkboard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "checkboard.h" 9 | #include 10 | #include 11 | 12 | CheckboardTextureGenerator::CheckboardTextureGenerator() 13 | { 14 | TextureGeneratorSetting color; 15 | color.name = "Color"; 16 | color.defaultvalue = QVariant(QColor(0, 0, 0, 255)); 17 | color.order = 1; 18 | configurables.insert("color", color); 19 | 20 | TextureGeneratorSetting brickwidth; 21 | brickwidth.name = "Brick width"; 22 | brickwidth.defaultvalue = QVariant((int) 10); 23 | brickwidth.min = QVariant(1); 24 | brickwidth.max = QVariant(300); 25 | brickwidth.order = 2; 26 | configurables.insert("brickwidth", brickwidth); 27 | 28 | TextureGeneratorSetting brickheight; 29 | brickheight.name = "Brick height"; 30 | brickheight.defaultvalue = QVariant((int) 10); 31 | brickheight.min = QVariant(1); 32 | brickheight.max = QVariant(300); 33 | brickheight.order = 3; 34 | configurables.insert("brickheight", brickheight); 35 | 36 | TextureGeneratorSetting offsetx; 37 | offsetx.name = "Offset left"; 38 | offsetx.defaultvalue = QVariant((int) 0); 39 | offsetx.min = QVariant(-100); 40 | offsetx.max = QVariant(100); 41 | offsetx.order = 4; 42 | configurables.insert("offsetx", offsetx); 43 | 44 | TextureGeneratorSetting offsety; 45 | offsety.name = "Offset top"; 46 | offsety.defaultvalue = QVariant((int) 0); 47 | offsety.min = QVariant(-100); 48 | offsety.max = QVariant(100); 49 | offsety.order = 5; 50 | configurables.insert("offsety", offsety); 51 | } 52 | 53 | 54 | void CheckboardTextureGenerator::generate(QSize size, 55 | TexturePixel* destimage, 56 | QMap sourceimages, 57 | TextureNodeSettings* settings) const 58 | { 59 | if (!settings || !destimage || !size.isValid()) { 60 | return; 61 | } 62 | QColor color = settings->value("color").value(); 63 | int brickheight = settings->value("brickheight").toDouble() * size.height() / 300; 64 | int brickwidth = settings->value("brickwidth").toDouble() * size.width() / 300; 65 | int offsetx = settings->value("offsetx").toDouble() * size.width() / 100; 66 | int offsety = settings->value("offsety").toDouble() * size.height() / 100; 67 | 68 | if (sourceimages.contains(0)) { 69 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 70 | } else { 71 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 72 | } 73 | QImage tempimage = QImage(size.width(), size.height(), QImage::Format_RGB32); 74 | memcpy(tempimage.bits(), destimage, size.width() * size.height() * sizeof(TexturePixel)); 75 | QPainter painter(&tempimage); 76 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 77 | painter.setBrush(QBrush(color, Qt::BrushStyle::SolidPattern)); 78 | painter.setPen(Qt::NoPen); 79 | 80 | bool invert = false; 81 | int currY = offsety - size.height() - brickheight; 82 | while (currY < size.height()) { 83 | invert = !invert; 84 | int currX = offsetx - size.width() - brickwidth; 85 | if (invert) { 86 | currX += brickwidth; 87 | } 88 | while (currX < size.width()) { 89 | painter.drawRect(currX, currY, brickwidth, brickheight); 90 | currX += brickwidth * 2; 91 | } 92 | currY += brickheight; 93 | } 94 | memcpy(destimage, tempimage.bits(), size.width() * size.height() * sizeof(TexturePixel)); 95 | } 96 | -------------------------------------------------------------------------------- /generators/checkboard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef CHECKBOARDTEXTUREGENERATOR_H 9 | #define CHECKBOARDTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The CheckboardTextureGenerator class 15 | */ 16 | class CheckboardTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | CheckboardTextureGenerator(); 20 | ~CheckboardTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Checkboard"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws a checkboard."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // CHECKBOARDTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/circle.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "circle.h" 9 | #include 10 | #include 11 | 12 | CircleTextureGenerator::CircleTextureGenerator() 13 | { 14 | TextureGeneratorSetting colorsetting; 15 | colorsetting.name = "Color"; 16 | colorsetting.description = "Color of the circle"; 17 | colorsetting.defaultvalue = QVariant(QColor(200, 100, 0, 200)); 18 | colorsetting.order = 1; 19 | configurables.insert("color", colorsetting); 20 | 21 | TextureGeneratorSetting innerRadius; 22 | innerRadius.name = "Inner radius"; 23 | innerRadius.description = "Inner radius of the circle in percent of width"; 24 | innerRadius.defaultvalue = QVariant((double) 0); 25 | innerRadius.min = QVariant(0); 26 | innerRadius.max = QVariant(200); 27 | innerRadius.order = 2; 28 | configurables.insert("innerradius", innerRadius); 29 | 30 | TextureGeneratorSetting outerRadius; 31 | outerRadius.name = "Outer radius"; 32 | outerRadius.description = "Outer radius of the circle in percent of width"; 33 | outerRadius.defaultvalue = QVariant((double) 100); 34 | outerRadius.min = QVariant(0); 35 | outerRadius.max = QVariant(200); 36 | outerRadius.order = 3; 37 | configurables.insert("outerradius", outerRadius); 38 | 39 | TextureGeneratorSetting offsetLeft; 40 | offsetLeft.name = "Offset left"; 41 | offsetLeft.description = "Inner radius of the circle in percent of width"; 42 | offsetLeft.defaultvalue = QVariant((double) 0); 43 | offsetLeft.min = QVariant(-100); 44 | offsetLeft.max = QVariant(100); 45 | offsetLeft.order = 4; 46 | configurables.insert("offsetleft", offsetLeft); 47 | 48 | TextureGeneratorSetting offsetTop; 49 | offsetTop.name = "Offset top"; 50 | offsetTop.description = "Outer radius of the circle in percent of width"; 51 | offsetTop.defaultvalue = QVariant((double) 0); 52 | offsetTop.min = QVariant(-100); 53 | offsetTop.max = QVariant(100); 54 | offsetTop.order = 5; 55 | configurables.insert("offsettop", offsetTop); 56 | } 57 | 58 | 59 | void CircleTextureGenerator::generate(QSize size, 60 | TexturePixel* destimage, 61 | QMap sourceimages, 62 | TextureNodeSettings* settings) const 63 | { 64 | if (!settings || !destimage || !size.isValid()) { 65 | return; 66 | } 67 | QColor color = settings->value("color").value(); 68 | double innerRadius = settings->value("innerradius").toDouble() * size.height() / 200.0; 69 | double outerRadius = settings->value("outerradius").toDouble() * size.height() / 200.0; 70 | int offsetLeft = settings->value("offsetleft").toDouble() * size.width() / 100; 71 | int offsetTop = settings->value("offsettop").toDouble() * size.height() / 100; 72 | 73 | bool blend = false; 74 | if (sourceimages.contains(0)) { 75 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 76 | blend = true; 77 | } else { 78 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 79 | } 80 | if (color.alpha() == 255) { 81 | blend = false; 82 | } 83 | double alpha = color.alphaF(); 84 | double srcAlpha = 1 - alpha; 85 | for (int y = 0; y < size.height(); y++) { 86 | for (int x = 0; x < size.width(); x++) { 87 | if (((pow(abs(size.width() / 2 - x + offsetLeft), 2) 88 | + pow(abs(size.height() / 2 - y + offsetTop), 2)) 89 | >= (pow(innerRadius, 2))) && 90 | ((pow(abs(size.width() / 2 - x + offsetLeft), 2) 91 | + pow(abs(size.height() / 2 - y + offsetTop), 2)) 92 | <= (pow(outerRadius, 2)))) { 93 | int thisPos = y * size.width() + x; 94 | destimage[thisPos].r = static_cast(alpha * color.red() + (blend ? (srcAlpha * destimage[thisPos].r) : 0)); 95 | destimage[thisPos].g = static_cast(alpha * color.green() + (blend ? (srcAlpha * destimage[thisPos].g) : 0)); 96 | destimage[thisPos].b = static_cast(alpha * color.blue() + (blend ? (srcAlpha * destimage[thisPos].b) : 0)); 97 | destimage[thisPos].a = static_cast(color.alpha() + (blend ? (srcAlpha * destimage[thisPos].a) : 0)); 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /generators/circle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef CIRCLETEXTUREGENERATOR_H 9 | #define CIRCLETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The CircleTextureGenerator class 15 | */ 16 | class CircleTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | CircleTextureGenerator(); 20 | ~CircleTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Circle"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws a filled circle."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // CIRCLETEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/cutout.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "cutout.h" 9 | 10 | CutoutTextureGenerator::CutoutTextureGenerator() 11 | { 12 | QStringList ordering; 13 | ordering.append("Slot 2 cut out from Slot 1"); 14 | ordering.append("Slot 1 cut out from Slot 2"); 15 | TextureGeneratorSetting order; 16 | order.name = "Order"; 17 | order.defaultvalue = QVariant(ordering); 18 | order.defaultindex = 0; 19 | order.order = 1; 20 | configurables.insert("order", order); 21 | 22 | TextureGeneratorSetting factor; 23 | factor.name = "Factor"; 24 | factor.defaultvalue = QVariant((int) 1); 25 | factor.min = 1; 26 | factor.max = 255; 27 | factor.defaultindex = 0; 28 | factor.order = 2; 29 | configurables.insert("factor", factor); 30 | } 31 | 32 | 33 | void CutoutTextureGenerator::generate(QSize size, TexturePixel* destimage, 34 | QMap sourceimages, 35 | TextureNodeSettings* settings) const 36 | { 37 | if (!settings || !destimage || !size.isValid()) { 38 | return; 39 | } 40 | QString order = settings->value("order").toString(); 41 | int factor = settings->value("factor").toInt(); 42 | 43 | int first = 0; 44 | int second = 1; 45 | if (order == "Slot 1 cut out from Slot 2") { 46 | first = 1; 47 | second = 0; 48 | } 49 | TexturePixel* originSource = nullptr; 50 | TexturePixel* subtractSource = nullptr; 51 | if (sourceimages.contains(first)) { 52 | originSource = sourceimages.value(first).data()->getData(); 53 | } 54 | if (sourceimages.contains(second)) { 55 | subtractSource = sourceimages.value(second).data()->getData(); 56 | } 57 | int numPixels = size.width() * size.height(); 58 | if (originSource && subtractSource) { 59 | memcpy(destimage, originSource, numPixels * sizeof(TexturePixel)); 60 | for (int i = 0; i < numPixels; i++) { 61 | if (destimage[i].a > (factor * subtractSource[i].a)) { 62 | destimage[i].a -= subtractSource[i].a; 63 | } else { 64 | destimage[i].a = 0; 65 | } 66 | } 67 | } else if (originSource) { 68 | memcpy(destimage, originSource, numPixels * sizeof(TexturePixel)); 69 | } else if (subtractSource) { 70 | memcpy(destimage, subtractSource, numPixels * sizeof(TexturePixel)); 71 | } else { 72 | memset(destimage, 0, numPixels * sizeof(TexturePixel)); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /generators/cutout.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef CUTOUTTEXTUREGENERATOR_H 9 | #define CUTOUTTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The CutoutTextureGenerator class 15 | */ 16 | class CutoutTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | CutoutTextureGenerator(); 20 | ~CutoutTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 2; } 26 | QString getName() const override { return QString("Cutout"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Cut alpha from one image using another."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Combiner; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // CUTOUTTEXTUREGENERATOR_H 36 | 37 | 38 | -------------------------------------------------------------------------------- /generators/displacementmap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include 9 | #include 10 | #include "displacementmap.h" 11 | 12 | using namespace std; 13 | 14 | DisplacementMapTextureGenerator::DisplacementMapTextureGenerator() 15 | { 16 | TextureGeneratorSetting angle; 17 | angle.name = "Angle"; 18 | angle.defaultvalue = QVariant((double) 45); 19 | angle.min = QVariant(-360); 20 | angle.max = QVariant(360); 21 | angle.order = 1; 22 | configurables.insert("angle", angle); 23 | 24 | TextureGeneratorSetting strength; 25 | strength.name = "Strength"; 26 | strength.defaultvalue = QVariant((double) 0.5); 27 | strength.min = QVariant(0); 28 | strength.max = QVariant(3); 29 | strength.order = 3; 30 | configurables.insert("strength", strength); 31 | 32 | TextureGeneratorSetting offset; 33 | offset.name = "Offset"; 34 | offset.defaultvalue = QVariant((double) 0); 35 | offset.min = QVariant(-360); 36 | offset.max = QVariant(360); 37 | offset.order = 4; 38 | configurables.insert("offset", offset); 39 | 40 | } 41 | 42 | 43 | void DisplacementMapTextureGenerator::generate(QSize size, 44 | TexturePixel* destimage, 45 | QMap sourceimages, 46 | TextureNodeSettings* settings) const 47 | { 48 | if (!settings || !destimage || !size.isValid()) { 49 | return; 50 | } 51 | if (!sourceimages.contains(0)) { 52 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 53 | return; 54 | } 55 | TexturePixel* sourceImage = sourceimages.value(0)->getData(); 56 | if (!sourceimages.contains(1)) { 57 | memcpy(destimage, sourceImage, size.width() * size.height() * sizeof(TexturePixel)); 58 | return; 59 | } 60 | TexturePixel* sourceMap = sourceimages.value(1)->getData(); 61 | 62 | double strength = settings->value("strength").toDouble() * size.width() / 500; 63 | double offset = settings->value("offset").toDouble() * size.width() / 100; 64 | double angle = settings->value("angle").toDouble(); 65 | angle = (angle / 180.0) * ((double) M_PI); 66 | 67 | for (int y = 0; y < size.height(); y++) { 68 | for (int x = 0; x < size.width(); x++) { 69 | double srcDistance = sourceMap[y * size.width() + x].intensityWithAlpha(); 70 | srcDistance *= strength; 71 | srcDistance -= offset; 72 | int xpos = x + srcDistance * sin(angle); 73 | int ypos = y - srcDistance * cos(angle); 74 | xpos = xpos > size.height() ? xpos % size.height() : 75 | (xpos < 0 ? xpos + size.width() : xpos); 76 | ypos = ypos > size.height() ? ypos % size.height() : 77 | (ypos < 0 ? ypos + size.height() : ypos); 78 | xpos = qMax(qMin(xpos, size.width() - 1), 0); 79 | ypos = qMax(qMin(ypos, size.height() - 1), 0); 80 | destimage[y * size.width() + x] = sourceImage[ypos * size.width() + xpos]; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /generators/displacementmap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef DISPLACEMENTMAPTEXTUREGENERATOR_H 9 | #define DISPLACEMENTMAPTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The DisplacementMapTextureGenerator class 15 | */ 16 | class DisplacementMapTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | DisplacementMapTextureGenerator(); 20 | ~DisplacementMapTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 2; } 26 | QString getSlotName(int num) override { 27 | if (num == 1) return QString("Map"); 28 | return QString("Source image"); 29 | } 30 | QString getName() const override { return QString("Displacement"); } 31 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 32 | QString getDescription() const override { 33 | return QString("Transforms the image based on a gray-scale transform map."); 34 | } 35 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 36 | 37 | private: 38 | TextureGeneratorSettings configurables; 39 | }; 40 | 41 | #endif // DISPLACEMENTMAPTEXTUREGENERATOR_H 42 | -------------------------------------------------------------------------------- /generators/empty.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "empty.h" 9 | 10 | void EmptyGenerator::generate(QSize size, TexturePixel* destimage, 11 | QMap sourceimages, 12 | TextureNodeSettings* settings) const 13 | { 14 | Q_UNUSED(settings); 15 | Q_UNUSED(sourceimages); 16 | if (destimage && size.isValid()) { 17 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /generators/empty.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef EMPTYGENERATOR_H 9 | #define EMPTYGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The EmptyGenerator class 15 | */ 16 | class EmptyGenerator : public TextureGenerator 17 | { 18 | public: 19 | EmptyGenerator() = default; 20 | ~EmptyGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 3; } 26 | QString getName() const override { return QString("Empty"); } 27 | const TextureGeneratorSettings& getSettings() const override { return _settings; } 28 | QString getDescription() const override { return QString("Empty generator."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings _settings; 33 | }; 34 | 35 | #endif // EMPTYGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/fill.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "fill.h" 9 | #include 10 | 11 | FillTextureGenerator::FillTextureGenerator() 12 | { 13 | TextureGeneratorSetting colorsetting; 14 | colorsetting.defaultvalue = QVariant(QColor(255, 255, 255, 255)); 15 | colorsetting.name = "Color"; 16 | colorsetting.description = "Color to fill the texture with."; 17 | configurables.insert("color", colorsetting); 18 | } 19 | 20 | 21 | void FillTextureGenerator::generate(QSize size, TexturePixel* destimage, 22 | QMap sourceimages, 23 | TextureNodeSettings* settings) const 24 | { 25 | Q_UNUSED(sourceimages); 26 | 27 | if (!settings || !destimage || !size.isValid()) { 28 | return; 29 | } 30 | QColor color = settings->value("color").value(); 31 | const int numpixels = size.width() * size.height(); 32 | TexturePixel filler(static_cast(color.red()), static_cast(color.green()), 33 | static_cast(color.blue()), static_cast(color.alpha())); 34 | for (int i = 0; i < numpixels; i++) { 35 | destimage[i] = filler; 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /generators/fill.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef FILLTEXTUREGENERATOR_H 9 | #define FILLTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The FillTextureGenerator class 15 | */ 16 | class FillTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | FillTextureGenerator(); 20 | ~FillTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 0; } 26 | QString getName() const override { return QString("Fill"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Fills the whole texture with the specified color."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // FILLTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/fire.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "fire.h" 9 | #include 10 | #include 11 | #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) 12 | #include 13 | #endif 14 | 15 | /** 16 | * @brief FireTextureGenerator::FireTextureGenerator 17 | * 18 | * The algorithm is taken from Lode's Computer Graphics Tutorial 19 | * http://lodev.org/cgtutor/fire.html 20 | */ 21 | FireTextureGenerator::FireTextureGenerator() 22 | { 23 | TextureGeneratorSetting falloff; 24 | falloff.defaultvalue = QVariant((double) 0.10); 25 | falloff.min = QVariant(0); 26 | falloff.max = QVariant(0.5); 27 | falloff.name = "Falloff"; 28 | falloff.order = 1; 29 | configurables.insert("falloff", falloff); 30 | 31 | TextureGeneratorSetting iterations; 32 | iterations.defaultvalue = QVariant((int) 150); 33 | iterations.min = QVariant(1); 34 | iterations.max = QVariant(400); 35 | iterations.name = "Iterations"; 36 | iterations.order = 2; 37 | configurables.insert("iterations", iterations); 38 | 39 | TextureGeneratorSetting randomize; 40 | randomize.defaultvalue = QVariant((int) 5); 41 | randomize.min = QVariant(1); 42 | randomize.max = QVariant(500); 43 | randomize.name = "Random seed"; 44 | randomize.order = 3; 45 | configurables.insert("randomize", randomize); 46 | } 47 | 48 | 49 | void FireTextureGenerator::generate(QSize size, TexturePixel* destimage, 50 | QMap sourceimages, 51 | TextureNodeSettings* settings) const 52 | { 53 | if (!settings || !destimage || !size.isValid()) { 54 | return; 55 | } 56 | double falloff = 0.245 + settings->value("falloff").toDouble() / 100; 57 | int iterations = settings->value("iterations").toInt(); 58 | uint randomize = settings->value("randomize").toUInt(); 59 | #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) 60 | qsrand(randomize); 61 | #else 62 | QRandomGenerator random(randomize); 63 | #endif 64 | // Speed things up by having a smaller rendering surface. 65 | int screenWidth = 150; 66 | int screenHeight = 150; 67 | auto* renderSurface = new TexturePixel[screenWidth * screenHeight]; 68 | auto* fire = new int[screenHeight * screenWidth]; //this buffer will contain the fire 69 | QColor palette[256]; //this will contain the color palette 70 | memset(fire, 0, screenWidth * screenWidth * sizeof(int)); 71 | 72 | for (int x = 0; x < 256; x++) { 73 | // generate the palette 74 | // Hue goes from 0 to 85: red to yellow 75 | // Saturation is always the maximum: 255 76 | // Lightness is 0..255 for x=0..128, and 255 for x=128..255 77 | palette[x] = QColor::fromHsl(x / 3, 255, std::min(255, x * 2)); 78 | } 79 | for (int i = 0; i < iterations; i++) { 80 | // randomize the bottom row of the fire buffer 81 | for (int x = 0; x < screenWidth; x++) { 82 | fire[(screenHeight - 1) * screenWidth + x] = 83 | #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) 84 | abs(32768 + qrand()) % 256; 85 | #else 86 | abs(32768 + random.bounded(RAND_MAX)) % 256; 87 | #endif 88 | 89 | } 90 | // do the fire calculations for every pixel 91 | for (int y = 0; y < screenHeight - 1; y++) { 92 | for (int x = 0; x < screenWidth; x++) { 93 | fire[y * screenWidth + x] = (int) 94 | ((fire[screenWidth * ((y + 1) % screenHeight) + ((x - 1 + screenWidth) % screenWidth)] 95 | + fire[screenWidth * ((y + 2) % screenHeight) + ((x) % screenWidth)] 96 | + fire[screenWidth * ((y + 1) % screenHeight) + ((x + 1) % screenWidth)] 97 | + fire[screenWidth * ((y + 3) % screenHeight) + ((x) % screenWidth)]) 98 | * falloff) % 255; 99 | } 100 | } 101 | for (int y = 0; y < screenHeight; y++) { 102 | for (int x = 0; x < screenWidth; x++) { 103 | int thisPos = y * screenWidth + x; 104 | renderSurface[thisPos].r = palette[fire[y * screenWidth + x]].red(); 105 | renderSurface[thisPos].g = palette[fire[y * screenWidth + x]].green(); 106 | renderSurface[thisPos].b = palette[fire[y * screenWidth + x]].blue(); 107 | renderSurface[thisPos].a = renderSurface[thisPos].r; 108 | } 109 | } 110 | } 111 | delete[] fire; 112 | QImage tempimage = QImage(screenWidth, screenHeight, QImage::Format_ARGB32); 113 | memcpy(tempimage.bits(), renderSurface, screenWidth * screenHeight * sizeof(TexturePixel)); 114 | tempimage = tempimage.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 115 | 116 | QImage destobject(size.width(), size.height(), QImage::Format_ARGB32); 117 | if (sourceimages.contains(0)) { 118 | memcpy(destobject.bits(), sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 119 | } else { 120 | memset(destobject.bits(), 0, size.width() * size.height() * sizeof(TexturePixel)); 121 | } 122 | QPainter painter(&destobject); 123 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 124 | painter.drawImage(QPoint(0, 0), tempimage); 125 | memcpy(destimage, destobject.bits(), size.width() * size.height() * sizeof(TexturePixel)); 126 | } 127 | -------------------------------------------------------------------------------- /generators/fire.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef FIRETEXTUREGENERATOR_H 9 | #define FIRETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The FireTextureGenerator class 15 | * 16 | * The algorithm is taken from Lode's Computer Graphics Tutorial 17 | * http://lodev.org/cgtutor/fire.html 18 | */ 19 | class FireTextureGenerator : public TextureGenerator 20 | { 21 | public: 22 | FireTextureGenerator(); 23 | ~FireTextureGenerator() override = default; 24 | void generate(QSize size, 25 | TexturePixel* destimage, 26 | QMap sourceimages, 27 | TextureNodeSettings* settings) const override; 28 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 29 | int getNumSourceSlots() const override { return 1; } 30 | QString getName() const override { return "Fire"; } 31 | QString getDescription() const override { return QString("Early 90's fire effect"); } 32 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 33 | 34 | private: 35 | double noise(double x, double y) const; 36 | double findnoise2(double x,double y) const; 37 | double interpolate(double a, double b, double x) const; 38 | 39 | TextureGeneratorSettings configurables; 40 | }; 41 | 42 | #endif // FIRETEXTUREGENERATOR_H 43 | -------------------------------------------------------------------------------- /generators/gaussianblur.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "gaussianblur.h" 9 | #include 10 | #include 11 | 12 | GaussianBlurTextureGenerator::GaussianBlurTextureGenerator() 13 | { 14 | TextureGeneratorSetting neighbourssetting; 15 | neighbourssetting.defaultvalue = QVariant((int) 1); 16 | neighbourssetting.name = "Neighbours"; 17 | neighbourssetting.description = "Number of neighbours"; 18 | neighbourssetting.min = QVariant(1); 19 | neighbourssetting.max = QVariant(30); 20 | neighbourssetting.order = 1; 21 | configurables.insert("numneighbours", neighbourssetting); 22 | 23 | TextureGeneratorSetting weightsetting; 24 | weightsetting.defaultvalue = QVariant((double) 1); 25 | weightsetting.name = "Weight"; 26 | weightsetting.description = ""; 27 | weightsetting.min = QVariant(0); 28 | weightsetting.max = QVariant(4); 29 | weightsetting.order = 2; 30 | configurables.insert("weight", weightsetting); 31 | } 32 | 33 | 34 | float* GaussianBlurTextureGenerator::ComputeGaussianKernel(const int inRadius, const float radiusModifier) const 35 | { 36 | int mem_amount = (inRadius * 2) + 1; 37 | auto* gaussian_kernel = new float[mem_amount]; 38 | 39 | float twoRadiusSquaredRecip = 0.5 / (inRadius * inRadius); 40 | float sqrtTwoPiTimesRadiusRecip = 1.0 / (sqrt(M_PI * 2) * inRadius); 41 | 42 | // Create Gaussian Kernel 43 | int r = -inRadius; 44 | float sum = 0; 45 | for (int i = 0; i < mem_amount; i++) { 46 | float x = r * radiusModifier; 47 | x = x * x; 48 | float v = sqrtTwoPiTimesRadiusRecip * exp(-x * twoRadiusSquaredRecip); 49 | gaussian_kernel[i] = v; 50 | sum += v; 51 | r++; 52 | } 53 | // Normalize distribution 54 | float div = sum; 55 | for (int i = 0; i < mem_amount; i++) { 56 | gaussian_kernel[i] /= div; 57 | } 58 | return gaussian_kernel; 59 | } 60 | 61 | 62 | // Calculates the Gaussian Blur and stores the result on the height map given 63 | void GaussianBlurTextureGenerator::generate(QSize size, 64 | TexturePixel* destimage, 65 | QMap sourceimages, 66 | TextureNodeSettings* settings) const 67 | { 68 | if (!settings || !destimage || !size.isValid()) { 69 | return; 70 | } 71 | int numNeightbours = settings->value("numneighbours").toInt(); 72 | float inWeight = settings->value("weight").toFloat(); 73 | 74 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 75 | 76 | if (!sourceimages.contains(0)) { 77 | return; 78 | } 79 | TexturePixel* sourceImage = sourceimages.value(0).data()->getData(); 80 | 81 | int pixels_on_row = 1 + (numNeightbours * 2); 82 | 83 | float* gaussian_kernel = ComputeGaussianKernel(numNeightbours, inWeight); 84 | 85 | for (int y = 0; y < size.height(); y++) { 86 | int row = y * size.width(); 87 | for (int x = 0; x < size.width(); x++) { 88 | TexturePixel blurred_value(0, 0, 0, 0); 89 | for (int xoffset = 0; xoffset < pixels_on_row; xoffset++) { 90 | int sx = x - numNeightbours + xoffset; 91 | if (sx < 0) { 92 | sx = 0; 93 | } else if (sx > size.width() - 1){ 94 | sx = size.width() - 1; 95 | } 96 | // Calculate newly blurred value 97 | int pixelPos = row + sx; 98 | blurred_value.r += gaussian_kernel[xoffset] * sourceImage[pixelPos].r; 99 | blurred_value.g += gaussian_kernel[xoffset] * sourceImage[pixelPos].g; 100 | blurred_value.b += gaussian_kernel[xoffset] * sourceImage[pixelPos].b; 101 | blurred_value.a += gaussian_kernel[xoffset] * sourceImage[pixelPos].a; 102 | } 103 | // Set our calculated value to our temp map 104 | destimage[y * size.width() + x] = blurred_value; 105 | } 106 | } 107 | for(int y = 0; y < size.height(); y++) { 108 | for(int x = 0; x < size.width(); x++) { 109 | TexturePixel blurred_value(0, 0, 0, 0); 110 | for (int yoffset = 0; yoffset < pixels_on_row; yoffset++) { 111 | int sy = y - numNeightbours + yoffset; 112 | if (sy < 0) { 113 | sy = 0; 114 | } else if (sy > size.height() - 1){ 115 | sy = size.height() - 1; 116 | } 117 | int pixelPos = sy * size.width() + x; 118 | // Calculate blurred value 119 | blurred_value.r += gaussian_kernel[yoffset] * destimage[pixelPos].r; 120 | blurred_value.g += gaussian_kernel[yoffset] * destimage[pixelPos].g; 121 | blurred_value.b += gaussian_kernel[yoffset] * destimage[pixelPos].b; 122 | blurred_value.a += gaussian_kernel[yoffset] * destimage[pixelPos].a; 123 | } 124 | 125 | // Set the original height map value to our computed value 126 | // This is the actual blurred value (previously scaled) 127 | destimage[y * size.width() + x] = blurred_value; 128 | } 129 | } 130 | delete[] gaussian_kernel; 131 | } 132 | -------------------------------------------------------------------------------- /generators/gaussianblur.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef GAUSSIANBLURTEXTUREGENERATOR_H 9 | #define GAUSSIANBLURTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The GaussianBlurTextureGenerator class 15 | */ 16 | class GaussianBlurTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | GaussianBlurTextureGenerator(); 20 | ~GaussianBlurTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Gaussian blur"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | float* ComputeGaussianKernel(const int inRadius, const float inWeight) const; 34 | }; 35 | 36 | #endif // GAUSSIANBLURTEXTUREGENERATOR_H 37 | -------------------------------------------------------------------------------- /generators/glow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef GLOWTEXTUREGENERATOR_H 9 | #define GLOWTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The GlowTextureGenerator class 15 | */ 16 | class GlowTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | GlowTextureGenerator(); 20 | ~GlowTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Glow"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Adds a glow around the object."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // GLOWTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/gradient.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef GRADIENTTEXTUREGENERATOR_H 9 | #define GRADIENTTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The GradientTextureGenerator class 15 | */ 16 | class GradientTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | GradientTextureGenerator(); 20 | ~GradientTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Gradient"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws a filled Gradient."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // GRADIENTTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/greyscale.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "greyscale.h" 9 | 10 | void GreyscaleTextureGenerator::generate(QSize size, 11 | TexturePixel* destimage, 12 | QMap sourceimages, 13 | TextureNodeSettings* settings) const 14 | { 15 | Q_UNUSED(settings); 16 | 17 | if (!destimage || !size.isValid()) { 18 | return; 19 | } 20 | if (!sourceimages.contains(0)) { 21 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 22 | return; 23 | } 24 | TexturePixel* sourceImage = sourceimages.value(0).data()->getData(); 25 | 26 | for (int j = 0; j < size.height(); j++) { 27 | for (int i = 0; i < size.width(); i++) { 28 | int pixelpos = j * size.width() + i; 29 | TexturePixel sourcePixel = sourceImage[pixelpos]; 30 | auto color = static_cast(sourcePixel.intensity() * 255); 31 | destimage[pixelpos].r = color; 32 | destimage[pixelpos].g = color; 33 | destimage[pixelpos].b = color; 34 | destimage[pixelpos].a = sourcePixel.a; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /generators/greyscale.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef GREYSCALETEXTUREGENERATOR_H 9 | #define GREYSCALETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The GreyscaleTextureGenerator class 15 | */ 16 | class GreyscaleTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | GreyscaleTextureGenerator() = default; 20 | ~GreyscaleTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Greyscale"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // GREYSCALETEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/invert.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "invert.h" 9 | 10 | InvertTextureGenerator::InvertTextureGenerator() 11 | { 12 | QStringList options; 13 | options.append("Yes"); 14 | options.append("No"); 15 | 16 | TextureGeneratorSetting channelRed; 17 | channelRed.name = "Invert red"; 18 | channelRed.order = 0; 19 | channelRed.defaultindex = 0; 20 | channelRed.defaultvalue = QVariant(options); 21 | configurables.insert("channelRed", channelRed); 22 | 23 | TextureGeneratorSetting channelGreen; 24 | channelGreen.name = "Invert green"; 25 | channelGreen.order = 1; 26 | channelGreen.defaultindex = 0; 27 | channelGreen.defaultvalue = QVariant(options); 28 | configurables.insert("channelGreen", channelGreen); 29 | 30 | TextureGeneratorSetting channelBlue; 31 | channelBlue.name = "Invert blue"; 32 | channelBlue.order = 2; 33 | channelBlue.defaultindex = 0; 34 | channelBlue.defaultvalue = QVariant(options); 35 | configurables.insert("channelBlue", channelBlue); 36 | 37 | TextureGeneratorSetting channelAlpha; 38 | channelAlpha.name = "Invert alpha"; 39 | channelAlpha.order = 3; 40 | channelAlpha.defaultindex = 1; 41 | channelAlpha.defaultvalue = QVariant(options); 42 | configurables.insert("channelAlpha", channelAlpha); 43 | } 44 | 45 | void InvertTextureGenerator::generate(QSize size, TexturePixel* destimage, 46 | QMap sourceimages, 47 | TextureNodeSettings* settings) const 48 | { 49 | if (!settings || !destimage || !size.isValid()) { 50 | return; 51 | } 52 | auto channelRedStr = settings->value("channelRed").toString(); 53 | auto channelGreenStr = settings->value("channelGreen").toString(); 54 | auto channelBlueStr = settings->value("channelBlue").toString(); 55 | auto channelAlphaStr = settings->value("channelAlpha").toString(); 56 | int numPixels = size.width() * size.height(); 57 | TexturePixel* source = nullptr; 58 | if (sourceimages.contains(0)) { 59 | source = sourceimages.value(0).data()->getData(); 60 | } 61 | if (!source) { 62 | memset(destimage, 0, numPixels * sizeof(TexturePixel)); 63 | return; 64 | } 65 | memcpy(destimage, source, numPixels * sizeof(TexturePixel)); 66 | 67 | bool channelRedInvert = false; 68 | bool channelGreenInvert = false; 69 | bool channelBlueInvert = false; 70 | bool channelAlphaInvert = false; 71 | if (channelRedStr == "Yes") { 72 | channelRedInvert = true; 73 | } 74 | if (channelGreenStr == "Yes") { 75 | channelGreenInvert = true; 76 | } 77 | if (channelBlueStr == "Yes") { 78 | channelBlueInvert = true; 79 | } 80 | if (channelAlphaStr == "Yes") { 81 | channelAlphaInvert = true; 82 | } 83 | for (int thisPos = 0; thisPos < numPixels; thisPos++) { 84 | if (channelRedInvert) { 85 | destimage[thisPos].r = 255 - destimage[thisPos].r; 86 | } 87 | if (channelGreenInvert) { 88 | destimage[thisPos].g = 255 - destimage[thisPos].g; 89 | } 90 | if (channelBlueInvert) { 91 | destimage[thisPos].b = 255 - destimage[thisPos].b; 92 | } 93 | if (channelAlphaInvert) { 94 | destimage[thisPos].a = 255 - destimage[thisPos].a; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /generators/invert.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef INVERTTEXTUREGENERATOR_H 9 | #define INVERTTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The InvertTextureGenerator class 15 | */ 16 | class InvertTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | InvertTextureGenerator(); 20 | ~InvertTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Invert"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Inverts the colors."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // INVERTTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/javascript.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef JSTEXGENMANAGER_H 9 | #define JSTEXGENMANAGER_H 10 | 11 | #include "texturegenerator.h" 12 | #include 13 | #include 14 | 15 | class GeneratorFileFinder; 16 | class JsTexGen; 17 | class TextureProject; 18 | 19 | /** 20 | * @brief The JSTexGenManager class 21 | */ 22 | class JSTexGenManager : public QObject 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit JSTexGenManager(TextureProject* project); 28 | ~JSTexGenManager() override; 29 | 30 | public slots: 31 | void setDirectory(const QString& path, bool forceScan=false); 32 | void addGenerator(JsTexGen* generator); 33 | void setEnabled(bool); 34 | void settingsUpdated(); 35 | 36 | signals: 37 | void generatorAdded(TextureGeneratorPtr); 38 | void generatorRemoved(TextureGeneratorPtr); 39 | void scanDirectory(QString); 40 | 41 | private: 42 | QString directoryPath; 43 | GeneratorFileFinder* filefinder; 44 | QThread* filefinderthread; 45 | TextureProject* project; 46 | bool enabled; 47 | bool hasScannedDirectory; 48 | }; 49 | 50 | /** 51 | * @brief The JsTexGen class 52 | */ 53 | class JsTexGen : public TextureGenerator 54 | { 55 | public: 56 | explicit JsTexGen(const QString& jsContent); 57 | ~JsTexGen() override = default; 58 | void generate(QSize size, TexturePixel* destimage, 59 | QMap sourceimages, 60 | TextureNodeSettings* settings) const override; 61 | 62 | int getNumSourceSlots() const override { return numSlots; } 63 | QString getName() const override { return name; } 64 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 65 | QString getDescription() const override { return description; } 66 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 67 | bool isValid(); 68 | 69 | private: 70 | TextureGeneratorSettings configurables; 71 | QString name; 72 | QString description; 73 | QString scriptContent; 74 | mutable QReadWriteLock mutex; 75 | int numSlots; 76 | bool valid; 77 | bool separateColorChannels; 78 | }; 79 | 80 | /** 81 | * @brief The GeneratorFileFinder class 82 | */ 83 | class GeneratorFileFinder : public QObject 84 | { 85 | Q_OBJECT 86 | public slots: 87 | void abort(); 88 | void scanDirectory(QString basepath); 89 | signals: 90 | void scanFinished(); 91 | void generatorFound(JsTexGen* filename); 92 | private: 93 | bool aborted; 94 | }; 95 | 96 | #endif // JSTEXGENMANAGER_H 97 | -------------------------------------------------------------------------------- /generators/lens.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "lens.h" 9 | #include 10 | #include 11 | 12 | LensTextureGenerator::LensTextureGenerator() 13 | { 14 | TextureGeneratorSetting offsetleft; 15 | offsetleft.defaultvalue = QVariant((int) 0); 16 | offsetleft.name = "Offset left"; 17 | offsetleft.min = QVariant(-100); 18 | offsetleft.max = QVariant(100); 19 | offsetleft.order = 0; 20 | configurables.insert("offsetleft", offsetleft); 21 | 22 | TextureGeneratorSetting offsettop; 23 | offsettop.defaultvalue = QVariant((int) 0); 24 | offsettop.name = "Offset top"; 25 | offsettop.min = QVariant(-100); 26 | offsettop.max = QVariant(100); 27 | offsettop.order = 1; 28 | configurables.insert("offsettop", offsettop); 29 | 30 | TextureGeneratorSetting size; 31 | size.defaultvalue = QVariant((double) 50); 32 | size.name = "Size"; 33 | size.min = QVariant(0); 34 | size.max = QVariant(300); 35 | size.order = 2; 36 | configurables.insert("size", size); 37 | 38 | TextureGeneratorSetting strength; 39 | strength.defaultvalue = QVariant((double) 200); 40 | strength.name = "Strength"; 41 | strength.min = QVariant(0); 42 | strength.max = QVariant(300); 43 | strength.order = 3; 44 | configurables.insert("strength", strength); 45 | } 46 | 47 | 48 | void LensTextureGenerator::generate(QSize size, 49 | TexturePixel* destimage, 50 | QMap sourceimages, 51 | TextureNodeSettings* settings) const 52 | { 53 | if (!settings || !destimage || !size.isValid()) { 54 | return; 55 | } 56 | int offsetleft = settings->value("offsetleft").toDouble() * size.width() / 100; 57 | int offsettop = settings->value("offsettop").toDouble() * size.height() / 100; 58 | int lenssize = settings->value("size").toDouble() * size.height() / 100; 59 | double strength = (300 - settings->value("strength").toDouble()) * size.width() / 100; 60 | if (!sourceimages.contains(0)) { 61 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 62 | return; 63 | } 64 | TexturePixel* sourceimage = sourceimages.value(0).data()->getData(); 65 | 66 | memcpy(destimage, sourceimage, size.width() * size.height() * sizeof(TexturePixel)); 67 | 68 | if (lenssize % 2) { 69 | lenssize += 1; 70 | } 71 | QPoint* lens = new QPoint[lenssize * lenssize]; 72 | int r = lenssize / 2; 73 | 74 | for (int y = 0; y < (lenssize >> 1); y++) { 75 | for (int x = 0; x < (lenssize >> 1); x++) { 76 | int ix = 0; 77 | int iy = 0; 78 | if ((x * x + y * y) < (r * r)) { 79 | double shift = (double) strength / 80 | sqrt(strength * strength - (x * x + y * y - r * r)); 81 | ix = x * shift - x; 82 | iy = y * shift - y; 83 | } 84 | lens[lenssize * (lenssize / 2 - y) + lenssize / 2 - x] = QPoint(-ix, -iy); 85 | lens[lenssize * (lenssize / 2 + y) + lenssize / 2 + x] = QPoint(ix, iy); 86 | lens[lenssize * (lenssize / 2 + y) + lenssize / 2 - x] = QPoint(-ix, iy); 87 | lens[lenssize * (lenssize / 2 - y) + lenssize / 2 + x] = QPoint(ix, -iy); 88 | } 89 | } 90 | for (int y = 0; y < lenssize; y++) { 91 | int ypos = y + size.height() / 2 + offsettop - lenssize / 2; 92 | for (int x = 0; x < lenssize; x++) { 93 | int xpos = x + size.width() / 2 + offsetleft - lenssize / 2; 94 | int destpos = ypos * size.width() + xpos; 95 | if (xpos >= 0 && xpos < size.width() && ypos >= 0 && ypos < size.height()) { 96 | int sourcex = xpos + lens[y * lenssize + x].x(); 97 | if (sourcex < 0) { 98 | sourcex += size.width(); 99 | } else { 100 | sourcex = sourcex % size.width(); 101 | } 102 | int sourcey = ypos + lens[y * lenssize + x].y(); 103 | if (sourcey < 0) { 104 | sourcey += size.height(); 105 | } else { 106 | sourcey = sourcey % size.height(); 107 | } 108 | destimage[destpos] = sourceimage[sourcey * size.width() + sourcex]; 109 | } 110 | } 111 | } 112 | delete[] lens; 113 | } 114 | -------------------------------------------------------------------------------- /generators/lens.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef LENSTEXTUREGENERATOR_H 9 | #define LENSTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The LensTextureGenerator class 15 | */ 16 | class LensTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | LensTextureGenerator(); 20 | ~LensTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Lens"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Applies a lens effect."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // LENSTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/lines.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "lines.h" 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | LinesTextureGenerator::LinesTextureGenerator() 15 | { 16 | TextureGeneratorSetting color; 17 | color.name = "Line color"; 18 | color.defaultvalue = QVariant(QColor(255, 100, 50, 255)); 19 | color.order = 1; 20 | configurables.insert("color", color); 21 | 22 | TextureGeneratorSetting lineheight; 23 | lineheight.name = "Line width"; 24 | lineheight.defaultvalue = QVariant((int) 10); 25 | lineheight.min = QVariant(0); 26 | lineheight.max = QVariant(100); 27 | lineheight.order = 2; 28 | configurables.insert("lineheight", lineheight); 29 | 30 | TextureGeneratorSetting spacing; 31 | spacing.name = "Spacing"; 32 | spacing.defaultvalue = QVariant((int) 10); 33 | spacing.min = QVariant(0); 34 | spacing.max = QVariant(100); 35 | spacing.order = 3; 36 | configurables.insert("spacing", spacing); 37 | 38 | TextureGeneratorSetting offset; 39 | offset.name = "Offset"; 40 | offset.defaultvalue = QVariant((int) 0); 41 | offset.min = QVariant(-100); 42 | offset.max = QVariant(0); 43 | offset.order = 4; 44 | configurables.insert("offset", offset); 45 | 46 | TextureGeneratorSetting angle; 47 | angle.name = "Angle"; 48 | angle.defaultvalue = QVariant((double) 0); 49 | angle.min = QVariant(0); 50 | angle.max = QVariant(180); 51 | angle.order = 5; 52 | configurables.insert("angle", angle); 53 | } 54 | 55 | 56 | void LinesTextureGenerator::generate(QSize size, 57 | TexturePixel* destimage, 58 | QMap sourceimages, 59 | TextureNodeSettings* settings) const 60 | { 61 | if (!settings || !destimage || !size.isValid()) { 62 | return; 63 | } 64 | QColor color = settings->value("color").value(); 65 | int spacing = settings->value("spacing").toDouble() * size.height() / 100; 66 | int lineheight = settings->value("lineheight").toDouble() * size.height() / 100; 67 | int offset = settings->value("offset").toDouble() * size.height() / 100; 68 | double angle = settings->value("angle").toDouble(); 69 | 70 | if (sourceimages.contains(0)) { 71 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 72 | } else { 73 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 74 | } 75 | 76 | TexturePixel filler(color.red(), color.green(), color.blue(), 255); 77 | bool invert = false; 78 | if (angle > 90) { 79 | invert = true; 80 | angle = 180 - angle; 81 | } 82 | angle = (angle / 180.0) * ((double) M_PI); 83 | double x1 = 0; 84 | double y1 = -10000; 85 | double x1rot = (x1 * cos(angle)) - (y1 * sin(angle)); 86 | double y1rot = (y1 * cos(angle)) + (x1 * sin(angle)); 87 | x1 = x1rot; 88 | y1 = y1rot; 89 | double x2 = -x1; 90 | double y2 = -y1; 91 | for (int y = 0; y < size.height(); y++) { 92 | for (int x = 0; x < size.width(); x++) { 93 | double x3 = x; 94 | double y3 = y; 95 | double x4 = -10000; 96 | double y4 = y; 97 | double x4rot = ((x4 - x3) * cos(angle)) - ((y4 - y3) * sin(angle)) + x3; 98 | double y4rot = ((y4 - y3) * cos(angle)) + ((x4 - x3) * sin(angle)) + y3; 99 | x4 = x4rot; 100 | y4 = y4rot; 101 | double intersection_x = ((x2 * y1 - x1 * y2) * (x4 - x) - (x4 * y - x * y4) * (x2 - x1)) / 102 | ((x2 - x1) * (y4 - y) - (x4 - x) * (y2 - y1)); 103 | double intersection_y = ((x2 * y1 - x1 * y2) * (y4 - y) - (x4 * y - x * y4) * (y2 - y1)) / 104 | ((x2 - x1) * (y4 - y) - (x4 - x) * (y2 - y1)); 105 | int distance = sqrt((x - intersection_x) * (x - intersection_x) + (y - intersection_y) * (y - intersection_y)); 106 | if (((distance - offset) % (lineheight + spacing)) > spacing) { 107 | if (invert) { 108 | destimage[y * size.width() + size.width() - x - 1] = filler; 109 | } else { 110 | destimage[y * size.width() + x] = filler; 111 | } 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /generators/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef LINESTEXTUREGENERATOR_H 9 | #define LINESTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The LinesTextureGenerator class 15 | */ 16 | class LinesTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | LinesTextureGenerator(); 20 | ~LinesTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Lines"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws filled lines."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // LINESTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/merge.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "merge.h" 9 | 10 | void MergeTextureGenerator::generate(QSize size, TexturePixel* destimage, 11 | QMap sourceimages, 12 | TextureNodeSettings* settings) const 13 | { 14 | Q_UNUSED(settings); 15 | if (!destimage || !size.isValid()) { 16 | return; 17 | } 18 | int numPixels = size.width() * size.height(); 19 | memset(destimage, 0, numPixels * sizeof(TexturePixel)); 20 | QMapIterator sourceIterator(sourceimages); 21 | while (sourceIterator.hasNext()) { 22 | sourceIterator.next(); 23 | TexturePixel* newSource = sourceIterator.value().data()->getData(); 24 | for (int i = 0; i < numPixels; i++) { 25 | destimage[i] += newSource[i]; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /generators/merge.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef MERGETEXTUREGENERATOR_H 9 | #define MERGETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The MergeTextureGenerator class 15 | */ 16 | class MergeTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | MergeTextureGenerator() = default; 20 | ~MergeTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 10; } 26 | QString getName() const override { return QString("Merge"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Merge multiple textures."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Combiner; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // MERGETEXTUREGENERATOR_H 36 | 37 | 38 | -------------------------------------------------------------------------------- /generators/mirror.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "mirror.h" 9 | 10 | MirrorTextureGenerator::MirrorTextureGenerator() 11 | { 12 | QStringList directions; 13 | directions.append("Flip horizentally"); 14 | directions.append("Flip vertically"); 15 | directions.append("Mirror horizentally"); 16 | directions.append("Mirror vertically"); 17 | TextureGeneratorSetting direction; 18 | direction.name = "Direction"; 19 | direction.description = "Which way?"; 20 | direction.defaultvalue = QVariant(directions); 21 | configurables.insert("direction", direction); 22 | } 23 | 24 | 25 | void MirrorTextureGenerator::generate(QSize size, 26 | TexturePixel* destimage, 27 | QMap sourceimages, 28 | TextureNodeSettings* settings) const 29 | { 30 | if (!settings || !destimage || !size.isValid()) { 31 | return; 32 | } 33 | QString direction = settings->value("direction").toString(); 34 | 35 | if (!sourceimages.contains(0)) { 36 | memset(destimage, 255, size.width() * size.height() * sizeof(TexturePixel)); 37 | return; 38 | } 39 | TexturePixel* sourceImage = sourceimages.value(0)->getData(); 40 | 41 | if (direction == "Flip horizentally" || direction == "Flip vertically") { 42 | for (int y = 0; y < size.height(); y++) { 43 | bool horizontal = (direction == "Flip horizentally") ? true : false; 44 | int destrowstart = y * size.width(); 45 | if (horizontal) { 46 | for (int x = 0; x < size.width(); x++) { 47 | int sourcepos = destrowstart + size.width() - x; 48 | destimage[destrowstart + x] = sourceImage[sourcepos]; 49 | } 50 | } else { 51 | int sourcerowstart = (size.height() - y - 1) * size.width(); 52 | for (int x = 0; x < size.width(); x++) { 53 | destimage[destrowstart + x] = sourceImage[sourcerowstart + x]; 54 | } 55 | } 56 | } 57 | } else if (size.width() % 2 == 0) { 58 | if (direction == "Mirror horizentally") { 59 | for (int y = 0; y < size.height(); y++) { 60 | int destrowstart = y * size.width(); 61 | for (int x = 0; x < size.width(); x+=2) { 62 | TexturePixel color; 63 | color.r = (int) (sourceImage[destrowstart + x].r + sourceImage[destrowstart + x + 1].r) / 2; 64 | color.g = (int) (sourceImage[destrowstart + x].g + sourceImage[destrowstart + x + 1].g) / 2; 65 | color.b = (int) (sourceImage[destrowstart + x].b + sourceImage[destrowstart + x + 1].b) / 2; 66 | color.a = (int) (sourceImage[destrowstart + x].a + sourceImage[destrowstart + x + 1].a) / 2; 67 | destimage[destrowstart + x / 2] = color; 68 | destimage[destrowstart + size.width() - 1 - x / 2] = color; 69 | } 70 | } 71 | } else if (direction == "Mirror vertically") { 72 | int height = size.height(); 73 | int width = size.width(); 74 | for (int x = 0; x < size.width(); x++) { 75 | for (int y = 0; y < size.height(); y+=2) { 76 | TexturePixel color; 77 | color.r = (int) (sourceImage[y * width + x].r + sourceImage[(y + 1) * width + x].r) / 2; 78 | color.g = (int) (sourceImage[y * width + x].g + sourceImage[(y + 1) * width + x].g) / 2; 79 | color.b = (int) (sourceImage[y * width + x].b + sourceImage[(y + 1) * width + x].b) / 2; 80 | color.a = (int) (sourceImage[y * width + x].a + sourceImage[(y + 1) * width + x].a) / 2; 81 | destimage[y * width / 2 + x] = color; 82 | destimage[(height - 1 - y / 2) * width + x] = color; 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /generators/mirror.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef MIRRORTEXTUREGENERATOR_H 9 | #define MIRRORTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The MirrorTextureGenerator class 15 | */ 16 | class MirrorTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | MirrorTextureGenerator(); 20 | ~MirrorTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Mirror"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | 36 | #endif // MIRRORTEXTUREGENERATOR_H 37 | -------------------------------------------------------------------------------- /generators/modifylevels.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "modifylevels.h" 9 | 10 | ModifyLevelsTextureGenerator::ModifyLevelsTextureGenerator() 11 | { 12 | TextureGeneratorSetting channel; 13 | channel.name = "Channels"; 14 | QStringList channels; 15 | channels.append("All channels"); 16 | channels.append("All colors, not alpha"); 17 | channels.append("Only red"); 18 | channels.append("Only green"); 19 | channels.append("Only blue"); 20 | channels.append("Only alpha"); 21 | channel.description = ""; 22 | channel.order = 0; 23 | channel.defaultindex = 1; 24 | channel.defaultvalue = QVariant(channels); 25 | configurables.insert("channel", channel); 26 | 27 | TextureGeneratorSetting mode; 28 | mode.name = "Mode"; 29 | QStringList modes; 30 | modes.append("Multiply"); 31 | modes.append("Add"); 32 | mode.defaultvalue = QVariant(modes); 33 | mode.order = 1; 34 | configurables.insert("mode", mode); 35 | 36 | TextureGeneratorSetting blendingAlpha; 37 | blendingAlpha.name = "Amount"; 38 | blendingAlpha.defaultvalue = QVariant((double) 100); 39 | blendingAlpha.min = -500; 40 | blendingAlpha.max = 500; 41 | blendingAlpha.order = 2; 42 | configurables.insert("level", blendingAlpha); 43 | } 44 | 45 | 46 | void ModifyLevelsTextureGenerator::generate(QSize size, TexturePixel* destimage, 47 | QMap sourceimages, 48 | TextureNodeSettings* settings) const 49 | { 50 | if (!settings || !destimage || !size.isValid()) { 51 | return; 52 | } 53 | int numpixels = size.width() * size.height(); 54 | if (!sourceimages.contains(0)) { 55 | memset(destimage, 0, numpixels * sizeof(TexturePixel)); 56 | return; 57 | } 58 | memcpy(destimage, sourceimages.value(0)->getData(), numpixels * sizeof(TexturePixel)); 59 | 60 | QString mode = settings->value("mode").toString(); 61 | QString channel = settings->value("channel").toString(); 62 | double levelFactor = settings->value("level").toDouble() / 100; 63 | int levelAbsolute = qMin(settings->value("level").toInt(), 255); 64 | 65 | bool r = false, g = false, b = false, a = false; 66 | if (channel == "All channels") { 67 | r = g = b = a = true; 68 | } else if (channel == "All colors, not alpha") { 69 | r = g = b = true; 70 | } else if (channel == "Only red") { 71 | r = true; 72 | } else if (channel == "Only green") { 73 | g = true; 74 | } else if (channel == "Only blue") { 75 | b = true; 76 | } else if (channel == "Only alpha") { 77 | a = true; 78 | } 79 | 80 | if (mode == "Add") { 81 | for (int i = 0; i < numpixels; i++) { 82 | if (r) { 83 | destimage[i].r = qMax(qMin(levelAbsolute + destimage[i].r, 255), 0); 84 | } 85 | if (g) { 86 | destimage[i].g = qMax(qMin(levelAbsolute + destimage[i].g, 255), 0); 87 | } 88 | if (b) { 89 | destimage[i].b = qMax(qMin(levelAbsolute + destimage[i].b, 255), 0); 90 | } 91 | if (a) { 92 | destimage[i].a = qMax(qMin(levelAbsolute + destimage[i].a, 255), 0); 93 | } 94 | } 95 | } else if (mode == "Multiply") { 96 | for (int i = 0; i < numpixels; i++) { 97 | if (r) { 98 | destimage[i].r = qMax(qMin((int) (levelFactor * destimage[i].r), 255), 0); 99 | } 100 | if (g) { 101 | destimage[i].g = qMax(qMin((int) (levelFactor * destimage[i].g), 255), 0); 102 | } 103 | if (b) { 104 | destimage[i].b = qMax(qMin((int) (levelFactor * destimage[i].b), 255), 0); 105 | } 106 | if (a) { 107 | destimage[i].a = qMax(qMin((int) (levelFactor * destimage[i].a), 255), 0); 108 | } 109 | } 110 | } 111 | } 112 | 113 | 114 | -------------------------------------------------------------------------------- /generators/modifylevels.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef MODIFYLEVELSTEXTUREGENERATOR_H 9 | #define MODIFYLEVELSTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The ModifyLevelsTextureGenerator class 15 | */ 16 | class ModifyLevelsTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | ModifyLevelsTextureGenerator(); 20 | ~ModifyLevelsTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Modify levels"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Modifies the different."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // MODIFYLEVELSTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/noise.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef NOISETEXTUREGENERATOR_H 9 | #define NOISETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The NoiseTextureGenerator class 15 | */ 16 | class NoiseTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | NoiseTextureGenerator(); 20 | ~NoiseTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Noise"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Pure noise."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // NOISETEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/normalmap.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "normalmap.h" 9 | #include 10 | 11 | void NormalMapTextureGenerator::generate(QSize size, 12 | TexturePixel* destimage, 13 | QMap sourceimages, 14 | TextureNodeSettings* settings) const 15 | { 16 | if (!settings || !destimage || !size.isValid()) { 17 | return; 18 | } 19 | 20 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 21 | 22 | if (!sourceimages.contains(0)) { 23 | return; 24 | } 25 | TexturePixel* sourceImage = sourceimages.value(0)->getData(); 26 | 27 | for (int y = 1; y < size.height() - 1; y++) { 28 | for (int x = 1; x < size.width() - 1; x++) { 29 | int pixelpos = y * size.width() + x; 30 | double topleft = sourceImage[(y - 1) * size.width() + x - 1].intensity(); 31 | double topmiddle = sourceImage[(y - 1) * size.width() + x].intensity(); 32 | double topright = sourceImage[(y - 1) * size.width() + x + 1].intensity(); 33 | double middleleft = sourceImage[y * size.width() + x - 1].intensity(); 34 | double middleright = sourceImage[y * size.width() + x + 1].intensity(); 35 | double lowerleft = sourceImage[(y + 1) * size.width() + x - 1].intensity(); 36 | double lowermiddle = sourceImage[(y + 1) * size.width() + x].intensity(); 37 | double lowerright = sourceImage[(y + 1) * size.width() + x + 1].intensity(); 38 | 39 | double pStrength = 2; 40 | 41 | const double dX = (topright + 2.0 * middleright + lowerright) - (topleft + 2.0 * middleleft + lowerleft); 42 | const double dY = (lowerleft + 2.0 * lowermiddle + lowerright) - (topleft + 2.0 * topmiddle + topright); 43 | const double dZ = 1.0 / pStrength; 44 | 45 | QVector3D vect(dX, dY, dZ); 46 | vect.normalize(); 47 | 48 | destimage[pixelpos].r = (vect.x() + 1.0) * 127.5; 49 | destimage[pixelpos].g = (vect.y() + 1.0) * 127.5; 50 | destimage[pixelpos].b = (vect.z() + 1.0) * 127.5; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /generators/normalmap.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef NORMALMAPTEXTUREGENERATOR_H 9 | #define NORMALMAPTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The NormalMapTextureGenerator class 15 | */ 16 | class NormalMapTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | NormalMapTextureGenerator() = default; 20 | ~NormalMapTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Normal-map"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | 36 | #endif // NORMALMAPTEXTUREGENERATOR_H 37 | -------------------------------------------------------------------------------- /generators/perlinnoise.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "perlinnoise.h" 9 | #include 10 | #include 11 | #include 12 | 13 | PerlinNoiseTextureGenerator::PerlinNoiseTextureGenerator() 14 | { 15 | TextureGeneratorSetting colorsetting; 16 | colorsetting.defaultvalue = QVariant(QColor(255, 255, 255)); 17 | colorsetting.name = "Color"; 18 | colorsetting.description = "Color of the circle"; 19 | colorsetting.order = 1; 20 | configurables.insert("color", colorsetting); 21 | 22 | TextureGeneratorSetting numOctaves; 23 | numOctaves.defaultvalue = QVariant((int) 5); 24 | numOctaves.name = "Octaves"; 25 | numOctaves.description = "Number of octaves"; 26 | numOctaves.order = 2; 27 | configurables.insert("numoctaves", numOctaves); 28 | 29 | TextureGeneratorSetting persistence; 30 | persistence.defaultvalue = QVariant((double) 0.5); 31 | persistence.name = "Persistence"; 32 | persistence.description = "This controls the roughness of the picture,"; 33 | persistence.order = 3; 34 | configurables.insert("persistence", persistence); 35 | 36 | TextureGeneratorSetting zoom; 37 | zoom.defaultvalue = QVariant((double) 75); 38 | zoom.min = QVariant(10); 39 | zoom.max = QVariant(200); 40 | zoom.name = "Zoom"; 41 | zoom.order = 4; 42 | configurables.insert("zoom", zoom); 43 | 44 | TextureGeneratorSetting randomizer; 45 | randomizer.defaultvalue = QVariant((double) 500); 46 | randomizer.min = QVariant(0); 47 | randomizer.max = QVariant(1000); 48 | randomizer.name = "Random seed"; 49 | randomizer.order = 5; 50 | configurables.insert("randomizer", randomizer); 51 | } 52 | 53 | 54 | double PerlinNoiseTextureGenerator::findnoise2(double x, double y) const 55 | { 56 | int n = (int) x + (int) y * 57; 57 | n = (n << 13) ^ n; 58 | int nn = (n * (n * n * 60493 + 19990303) + 1376312589)& 0x7fffffff; 59 | return 1.0 - ((double) nn / 1073741824.0); 60 | } 61 | 62 | 63 | double PerlinNoiseTextureGenerator::noise(double x, double y) const 64 | { 65 | double s = findnoise2((int) x, (int) y); 66 | double t = findnoise2((int) x + 1, (int) y); 67 | double u = findnoise2((int) x, (int) y + 1); 68 | double v = findnoise2((int) x + 1, (int) y + 1); 69 | double int1 = interpolate(s, t, x - (int) x); 70 | double int2 = interpolate(u, v, x - (int) x); 71 | return interpolate(int1, int2, y - (int) y); 72 | } 73 | 74 | 75 | double PerlinNoiseTextureGenerator::interpolate(double a, double b, double x) const 76 | { 77 | double f = (1.0 - cos(x * 3.1415927)) * 0.5; 78 | return a * (1.0 - f) + b * f; 79 | } 80 | 81 | 82 | void PerlinNoiseTextureGenerator::generate(QSize size, TexturePixel* destimage, 83 | QMap sourceimages, 84 | TextureNodeSettings* settings) const 85 | { 86 | if (!settings || !destimage || !size.isValid()) { 87 | return; 88 | } 89 | 90 | 91 | QColor color = settings->value("color").value(); 92 | int numOctaves = settings->value("numoctaves").toInt(); 93 | double persistence = settings->value("persistence").toDouble(); 94 | double zoom = settings->value("zoom").toDouble(); 95 | double randomizer = settings->value("randomizer").toDouble() * 1000; 96 | double xFactor = (double) 500 / size.width(); 97 | double yFactor = (double) 500 / size.height(); 98 | bool blend = false; 99 | TexturePixel* sourceImg = nullptr; 100 | if (sourceimages.contains(0)) { 101 | sourceImg = sourceimages.value(0)->getData(); 102 | blend = true; 103 | } 104 | for (int y = 0; y < size.height(); y++) { 105 | for (int x = 0; x < size.width(); x++) { 106 | double getnoise = 0; 107 | int thisPos = y * size.width() + x; 108 | 109 | for (int currOctave = 0; currOctave < numOctaves - 1; currOctave++) { 110 | double frequency = pow(2, currOctave); //This increases the frequency with every loop of the octave. 111 | double amplitude = pow(persistence, currOctave);//This decreases the amplitude with every loop of the octave. 112 | getnoise += noise(randomizer + static_cast(x) * xFactor * frequency / zoom, 113 | randomizer + static_cast(y) * yFactor / zoom * frequency) * amplitude; 114 | } 115 | auto pixelColor = static_cast((getnoise * 128.0) + 128.0); 116 | if (pixelColor > 255) { 117 | pixelColor = 255; 118 | } 119 | if (pixelColor < 0) { 120 | pixelColor = 0; 121 | } 122 | double fraction = (static_cast(pixelColor) / 255.0); 123 | double negVal = 1 - (static_cast(pixelColor) / 255.0); 124 | 125 | destimage[thisPos].r = qMin(qMax((int) (fraction * (float) color.red() + (blend ? (negVal * (float) sourceImg[thisPos].r) : 0)), 0), 255); 126 | destimage[thisPos].g = qMin(qMax((int) (fraction * (float) color.green() + (blend ? (negVal * (float) sourceImg[thisPos].g) : 0)), 0), 255); 127 | destimage[thisPos].b = qMin(qMax((int) (fraction * (float) color.blue() + (blend ? (negVal * (float) sourceImg[thisPos].b) : 0)), 0), 255); 128 | destimage[thisPos].a = 255; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /generators/perlinnoise.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef PERLINNOISETEXTUREGENERATOR_H 9 | #define PERLINNOISETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The PerlinNoiseTextureGenerator class 15 | */ 16 | class PerlinNoiseTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | PerlinNoiseTextureGenerator(); 20 | ~PerlinNoiseTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 26 | int getNumSourceSlots() const override { return 1; } 27 | QString getName() const override { return "Perlin noise"; } 28 | QString getDescription() const override { return QString("Basic Perlin Noise"); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | double noise(double x, double y) const; 33 | double findnoise2(double x,double y) const; 34 | double interpolate(double a, double b, double x) const; 35 | 36 | TextureGeneratorSettings configurables; 37 | }; 38 | 39 | #endif // PERLINNOISETEXTUREGENERATOR_H 40 | -------------------------------------------------------------------------------- /generators/pixelate.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "pixelate.h" 9 | 10 | PixelateTextureGenerator::PixelateTextureGenerator() 11 | { 12 | TextureGeneratorSetting width; 13 | width.defaultvalue = QVariant((double) 5); 14 | width.name = "Width"; 15 | width.min = QVariant(0); 16 | width.max = QVariant(50); 17 | width.group = "size"; 18 | width.order = 1; 19 | configurables.insert("width", width); 20 | 21 | TextureGeneratorSetting height; 22 | height.defaultvalue = QVariant((double) 5); 23 | height.name = "Height"; 24 | height.min = QVariant(0); 25 | height.max = QVariant(50); 26 | height.group = "size"; 27 | height.order = 2; 28 | configurables.insert("height", height); 29 | 30 | TextureGeneratorSetting offsetx; 31 | offsetx.defaultvalue = QVariant((double) 0); 32 | offsetx.name = "Offset left"; 33 | offsetx.min = QVariant(-50); 34 | offsetx.max = QVariant(50); 35 | offsetx.order = 3; 36 | configurables.insert("offsetx", offsetx); 37 | 38 | TextureGeneratorSetting offsety; 39 | offsety.defaultvalue = QVariant((double) 0); 40 | offsety.name = "Offset top"; 41 | offsety.min = QVariant(-50); 42 | offsety.max = QVariant(50); 43 | offsety.order = 4; 44 | configurables.insert("offsety", offsety); 45 | } 46 | 47 | 48 | void PixelateTextureGenerator::generate(QSize size, 49 | TexturePixel* destimage, 50 | QMap sourceimages, 51 | TextureNodeSettings* settings) const 52 | { 53 | if (!settings || !destimage || !size.isValid()) { 54 | return; 55 | } 56 | int width = qMax(settings->value("width").toDouble() / 100 * size.width(), (double) 1); 57 | int height = qMax(settings->value("height").toDouble() / 100 * size.height(), (double) 1); 58 | int offsetx = settings->value("offsetx").toDouble() / 100 * size.width(); 59 | int offsety = settings->value("offsety").toDouble() / 100 * size.height(); 60 | if (!sourceimages.contains(0)) { 61 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 62 | return; 63 | } 64 | TexturePixel* sourceImage = sourceimages.value(0).data()->getData(); 65 | int y = offsety - size.height(); 66 | while (y < size.height()) { 67 | if (y + height > 0) { 68 | int x = offsetx - size.width(); 69 | while (x < size.width()) { 70 | if (x + width > 0) { 71 | int totalPixels = 0; 72 | quint64 red = 0; 73 | quint64 green = 0; 74 | quint64 blue = 0; 75 | quint64 alpha = 0; 76 | for (int ypos = y; ypos < y + height; ypos++) { 77 | int currY = ypos; 78 | if (currY < 0) { 79 | currY += size.height() * 5; 80 | } 81 | currY %= size.height(); 82 | currY *= size.width(); 83 | for (int xpos = x; xpos < x + width; xpos++) { 84 | int currX = xpos; 85 | if (currX < 0) { 86 | currX += size.width() * 5; 87 | } 88 | currX %= size.width(); 89 | TexturePixel sourcePixel = sourceImage[currY + currX]; 90 | totalPixels++; 91 | red += sourcePixel.r; 92 | green += sourcePixel.g; 93 | blue += sourcePixel.b; 94 | alpha += sourcePixel.a; 95 | } 96 | } 97 | if (totalPixels > 0) { 98 | TexturePixel color(red / totalPixels, green / totalPixels, 99 | blue / totalPixels, alpha / totalPixels); 100 | int stopY = qMin(y + height, size.height()); 101 | for (int ypos = qMax(y, 0); ypos < stopY; ypos++) { 102 | int linestart = ypos * size.width(); 103 | int stopX = qMin(x + width, size.width()); 104 | for (int xpos = qMax(x, 0); xpos < stopX; xpos++) { 105 | destimage[linestart + xpos] = color; 106 | } 107 | } 108 | } 109 | } 110 | x += width; 111 | } 112 | } 113 | y += height; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /generators/pixelate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef PIXELATETEXTUREGENERATOR_H 9 | #define PIXELATETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The PixelateTextureGenerator class 15 | */ 16 | class PixelateTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | PixelateTextureGenerator(); 20 | ~PixelateTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Pixelate"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Pixelates the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // PIXELATETEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/pointillism.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | 9 | #include "pointillism.h" 10 | #include 11 | #include 12 | #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) 13 | #include 14 | #endif 15 | #include 16 | 17 | PointillismTextureGenerator::PointillismTextureGenerator() 18 | { 19 | TextureGeneratorSetting points; 20 | points.defaultvalue = QVariant((int) 10000); 21 | points.name = "Points"; 22 | points.min = QVariant(0); 23 | points.max = QVariant(250 * 1000); 24 | points.order = 1; 25 | configurables.insert("points", points); 26 | 27 | TextureGeneratorSetting width; 28 | width.defaultvalue = QVariant((double) 1); 29 | width.name = "Width"; 30 | width.min = QVariant(0.2); 31 | width.max = QVariant(50); 32 | width.order = 2; 33 | width.group = "size"; 34 | configurables.insert("width", width); 35 | 36 | TextureGeneratorSetting height; 37 | height.defaultvalue = QVariant((double) 1); 38 | height.name = "Height"; 39 | height.min = QVariant(0.2); 40 | height.max = QVariant(50); 41 | height.order = 3; 42 | height.group = "size"; 43 | configurables.insert("height", height); 44 | 45 | TextureGeneratorSetting includesource; 46 | includesource.defaultvalue = QVariant((bool) true); 47 | includesource.name = "Include source"; 48 | includesource.order = 4; 49 | configurables.insert("includesource", includesource); 50 | 51 | TextureGeneratorSetting antialiasing; 52 | antialiasing.defaultvalue = QVariant((bool) true); 53 | antialiasing.name = "Antialiasing"; 54 | antialiasing.order = 5; 55 | configurables.insert("antialiasing", antialiasing); 56 | 57 | TextureGeneratorSetting randseed; 58 | randseed.defaultvalue = QVariant((int) 500); 59 | randseed.name = "Random seed"; 60 | randseed.min = QVariant(0); 61 | randseed.max = QVariant(1000); 62 | randseed.order = 6; 63 | configurables.insert("randseed", randseed); 64 | } 65 | 66 | 67 | void PointillismTextureGenerator::generate(QSize size, 68 | TexturePixel* destimage, 69 | QMap sourceimages, 70 | TextureNodeSettings* settings) const 71 | { 72 | if (!settings || !destimage || !size.isValid()) { 73 | return; 74 | } 75 | double shapeWidth = settings->value("width").toDouble() * size.width() / 100; 76 | double shapeHeight = settings->value("height").toDouble() * size.height() / 100; 77 | int randseed = settings->value("randseed").toInt(); 78 | int points = settings->value("points").toInt(); 79 | bool includesource = settings->value("includesource").toBool(); 80 | bool antialiasing = settings->value("antialiasing").toBool(); 81 | 82 | if (!sourceimages.contains(0)) { 83 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 84 | return; 85 | } 86 | 87 | #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) 88 | srand(randseed); 89 | #else 90 | QRandomGenerator random(randseed); 91 | #endif 92 | 93 | TexturePixel* sourceImage = sourceimages.value(0)->getData(); 94 | if (includesource) { 95 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 96 | } else { 97 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 98 | } 99 | 100 | QImage tempimage = QImage(size.width(), size.height(), QImage::Format_RGB32); 101 | memcpy(tempimage.bits(), destimage, size.width() * size.height() * sizeof(TexturePixel)); 102 | 103 | QPainter painter(&tempimage); 104 | painter.setPen(Qt::NoPen); 105 | painter.setRenderHint(QPainter::Antialiasing, antialiasing); 106 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 107 | 108 | for (int i = 0; i < points; i++) { 109 | #if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) 110 | int x = qrand() % size.width(); 111 | int y = qrand() % size.height(); 112 | #else 113 | int x = random.bounded(0, size.width()); 114 | int y = random.bounded(0, size.height()); 115 | #endif 116 | TexturePixel sourcePixel = sourceImage[y * size.width() + x]; 117 | QColor sourceColor(sourcePixel.r, sourcePixel.g, sourcePixel.b, sourcePixel.a); 118 | painter.setBrush(QBrush(sourceColor, Qt::BrushStyle::SolidPattern)); 119 | painter.drawEllipse(QPointF(x, y), shapeWidth, shapeHeight); 120 | } 121 | memcpy(destimage, tempimage.bits(), size.width() * size.height() * sizeof(TexturePixel)); 122 | } 123 | -------------------------------------------------------------------------------- /generators/pointillism.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef POINTILLISMTEXTUREGENERATOR_H 9 | #define POINTILLISMTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The PointillismTextureGenerator class 15 | */ 16 | class PointillismTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | PointillismTextureGenerator(); 20 | ~PointillismTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Pointillism"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString(""); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // POINTILLISMTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/setchannels.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SETCHANNELSTEXTUREGENERATOR_H 9 | #define SETCHANNELSTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The SetChannelsTextureGenerator class 15 | */ 16 | class SetChannelsTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | enum Channels { 20 | none = 1, 21 | fill = 2, 22 | node1red = 3, 23 | node1green = 4, 24 | node1blue = 5, 25 | node1alpha = 6, 26 | node2red = 7, 27 | node2green = 8, 28 | node2blue = 9, 29 | node2alpha = 10 30 | }; 31 | 32 | SetChannelsTextureGenerator(); 33 | ~SetChannelsTextureGenerator() override = default; 34 | void generate(QSize size, 35 | TexturePixel* destimage, 36 | QMap sourceimages, 37 | TextureNodeSettings* settings) const override; 38 | int getNumSourceSlots() const override { return 2; } 39 | QString getName() const override { return QString("Set channels"); } 40 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 41 | QString getDescription() const override { return QString(""); } 42 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Combiner; } 43 | 44 | private: 45 | TextureGeneratorSettings configurables; 46 | Channels getChannelFromName(const QString& name) const; 47 | quint8 getColorFromChannel(const TexturePixel& firstColor, const TexturePixel& secondColor, 48 | Channels channel) const; 49 | }; 50 | 51 | #endif // SETCHANNELSTEXTUREGENERATOR_H 52 | 53 | 54 | -------------------------------------------------------------------------------- /generators/shadow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SHADOWTEXTUREGENERATOR_H 9 | #define SHADOWTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The ShadowTextureGenerator class 15 | */ 16 | class ShadowTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | ShadowTextureGenerator(); 20 | ~ShadowTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Shadow"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Adds a shadow under the object."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // SHADOWTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/sineplasma.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "sineplasma.h" 9 | #include 10 | #include 11 | #include 12 | 13 | SinePlasmaTextureGenerator::SinePlasmaTextureGenerator() 14 | { 15 | TextureGeneratorSetting colorsetting; 16 | colorsetting.defaultvalue = QVariant(QColor(255, 0, 0)); 17 | colorsetting.name = "Color"; 18 | colorsetting.description = "Color of the circle"; 19 | colorsetting.order = 1; 20 | configurables.insert("color", colorsetting); 21 | 22 | TextureGeneratorSetting xoffset; 23 | xoffset.defaultvalue = QVariant((double) 10); 24 | xoffset.name = "Offset left"; 25 | xoffset.description = "Offset along the x axis"; 26 | xoffset.min = QVariant(-100); 27 | xoffset.max = QVariant(100); 28 | xoffset.order = 2; 29 | configurables.insert("xoffset", xoffset); 30 | 31 | TextureGeneratorSetting yoffset; 32 | yoffset.defaultvalue = QVariant((double) 10); 33 | yoffset.name = "Offset top"; 34 | yoffset.description = "Offset along the y axis"; 35 | yoffset.min = QVariant(-100); 36 | yoffset.max = QVariant(100); 37 | yoffset.order = 3; 38 | configurables.insert("yoffset", yoffset); 39 | 40 | TextureGeneratorSetting xfrequency; 41 | xfrequency.defaultvalue = QVariant((double) 10); 42 | xfrequency.name = "Frequency X axis"; 43 | xfrequency.description = "How often it repeats along the y axis"; 44 | xfrequency.min = QVariant(0); 45 | xfrequency.max = QVariant(100); 46 | xfrequency.group = "frequencies"; 47 | xfrequency.order = 4; 48 | configurables.insert("xfrequency", xfrequency); 49 | 50 | TextureGeneratorSetting yfrequency; 51 | yfrequency.defaultvalue = QVariant((double) 10); 52 | yfrequency.name = "Frequency Y axis"; 53 | yfrequency.description = "How often it repeats along the y axis"; 54 | yfrequency.min = QVariant(0); 55 | yfrequency.max = QVariant(100); 56 | yfrequency.group = "frequencies"; 57 | yfrequency.order = 5; 58 | configurables.insert("yfrequency", yfrequency); 59 | } 60 | 61 | 62 | void SinePlasmaTextureGenerator::generate(QSize size, 63 | TexturePixel* destimage, 64 | QMap sourceimages, 65 | TextureNodeSettings* settings) const 66 | { 67 | if (!settings || !destimage || !size.isValid()) { 68 | return; 69 | } 70 | QColor color = settings->value("color").value(); 71 | double xoffset = settings->value("xoffset").toInt() * size.width() / 100; 72 | double yoffset = settings->value("yoffset").toInt() * size.height() / 100; 73 | double xfrequency = settings->value("xfrequency").toDouble() * 5 / size.width(); 74 | double yfrequency = settings->value("yfrequency").toDouble() * 5 / size.height(); 75 | 76 | if (sourceimages.contains(0)) { 77 | memcpy(destimage, sourceimages.value(0)->getData(), size.width() * size.height() * sizeof(TexturePixel)); 78 | } else { 79 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 80 | } 81 | 82 | for (int y = 0; y < size.height(); y++) { 83 | for (int x = 0; x < size.width(); x++) { 84 | double value = 0.5 + 0.25 * qSin((x - xoffset) * xfrequency) + 0.25 * qSin((y - yoffset) * yfrequency); 85 | double negVal = 1 - value; 86 | int pixelPos = y * size.width() + x; 87 | destimage[pixelPos].r = qMin(qMax((int) (value * (double) color.red() + 88 | negVal * (double) destimage[pixelPos].r), 0), 255); 89 | destimage[pixelPos].g = qMin(qMax((int) (value * (double) color.green() + 90 | negVal * (double) destimage[pixelPos].g), 0), 255); 91 | destimage[pixelPos].b = qMin(qMax((int) (value * (double) color.blue() + 92 | negVal * (double) destimage[pixelPos].b), 0), 255); 93 | destimage[pixelPos].a = qMin(qMax((int) (value * (double) color.alpha() + 94 | negVal * (double) destimage[pixelPos].a), (int) destimage[pixelPos].a), 255); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /generators/sineplasma.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SINEPLASMATEXTUREGENERATOR_H 9 | #define SINEPLASMATEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The SinePlasmaTextureGenerator class 15 | */ 16 | class SinePlasmaTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | SinePlasmaTextureGenerator(); 20 | ~SinePlasmaTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Sine plasma"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Repeating sine plasma."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // SINEPLASMATEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/sinetransform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SINETRANSFORMTEXTUREGENERATOR_H 9 | #define SINETRANSFORMTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The SineTransformTextureGenerator class 15 | */ 16 | class SineTransformTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | SineTransformTextureGenerator(); 20 | ~SineTransformTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Sine transform"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Stretches the texture along a sinus wave."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // SINETRANSFORMTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/square.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SQUARETEXTUREGENERATOR_H 9 | #define SQUARETEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The SquareTextureGenerator class 15 | */ 16 | class SquareTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | SquareTextureGenerator(); 20 | ~SquareTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Square"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws a square."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // SQUARETEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/stackblur.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef STACKBLURTEXTUREGENERATOR_H 9 | #define STACKBLURTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The StackBlurTextureGenerator class 15 | */ 16 | class StackBlurTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | StackBlurTextureGenerator(); 20 | ~StackBlurTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Stack Blur"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Blurs the source image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // STACKBLURTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/star.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | #ifndef STARTEXTUREGENERATOR_H 8 | #define STARTEXTUREGENERATOR_H 9 | 10 | #include "texturegenerator.h" 11 | 12 | /** 13 | * @brief The StarTextureGenerator class 14 | */ 15 | class StarTextureGenerator : public TextureGenerator 16 | { 17 | public: 18 | StarTextureGenerator(); 19 | ~StarTextureGenerator() override = default; 20 | void generate(QSize size, 21 | TexturePixel* destimage, 22 | QMap sourceimages, 23 | TextureNodeSettings* settings) const override; 24 | int getNumSourceSlots() const override { return 1; } 25 | QString getName() const override { return QString("Star"); } 26 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 27 | QString getDescription() const override { return QString("Draws a star."); } 28 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 29 | 30 | private: 31 | TextureGeneratorSettings configurables; 32 | }; 33 | 34 | #endif // STARTEXTUREGENERATOR_H 35 | -------------------------------------------------------------------------------- /generators/text.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTTEXTUREGENERATOR_H 9 | #define TEXTTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The TextTextureGenerator class 15 | */ 16 | class TextTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | TextTextureGenerator(); 20 | ~TextTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Text"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Draws a Text."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Generator; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // TEXTTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /generators/texturegenerator.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "texturegenerator.h" 9 | #include 10 | 11 | /** 12 | * @brief TextureGenerator::getSlotName 13 | * @param id Slot id 14 | * @return The name 15 | * Default name for slots. 16 | */ 17 | QString TextureGenerator::getSlotName(int id) 18 | { 19 | return QString("Slot %1").arg(id + 1); 20 | } 21 | -------------------------------------------------------------------------------- /generators/texturegenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXTUREGENERATOR_H 9 | #define TEXTUREGENERATOR_H 10 | 11 | #include "base/textureimage.h" 12 | #include "global.h" 13 | #include 14 | 15 | class TextureImage; 16 | 17 | /** 18 | * @brief The TextureGenerator class 19 | * 20 | * Pure abstract class for TextureGenerator. 21 | */ 22 | class TextureGenerator 23 | { 24 | public: 25 | enum class Type { Filter, Combiner, Generator }; 26 | 27 | virtual ~TextureGenerator() = default; 28 | virtual void generate(QSize size, 29 | TexturePixel* destimage, 30 | QMap sourceimages, 31 | TextureNodeSettings* settings) const = 0; 32 | virtual const TextureGeneratorSettings& getSettings() const = 0; 33 | virtual Type getType() const = 0; 34 | virtual int getNumSourceSlots() const = 0; 35 | virtual QString getName() const = 0; 36 | virtual QString getSlotName(int id); 37 | virtual QString getDescription() const = 0; 38 | }; 39 | 40 | /** 41 | * @brief TextureGeneratorPtr 42 | * 43 | * Thread-safe smart pointer for TextureGenerator 44 | */ 45 | typedef QSharedPointer TextureGeneratorPtr; 46 | 47 | #endif // TEXTUREGENERATOR_H 48 | -------------------------------------------------------------------------------- /generators/transform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TRANSFORMTEXTUREGENERATOR_H 9 | #define TRANSFORMTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The TransformTextureGenerator class 15 | */ 16 | class TransformTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | TransformTextureGenerator(); 20 | ~TransformTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Transform"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Resizes/translates/rotates."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | 36 | #endif // TRANSFORMTEXTUREGENERATOR_H 37 | -------------------------------------------------------------------------------- /generators/whirl.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "whirl.h" 9 | #include 10 | #include 11 | 12 | WhirlTextureGenerator::WhirlTextureGenerator() 13 | { 14 | TextureGeneratorSetting radius; 15 | radius.name = "Radius"; 16 | radius.defaultvalue = QVariant((double) 50); 17 | radius.min = QVariant(0); 18 | radius.max = QVariant(200); 19 | radius.order = 1; 20 | configurables.insert("radius", radius); 21 | 22 | TextureGeneratorSetting strength; 23 | strength.name = "Strength"; 24 | strength.defaultvalue = QVariant((double) 40); 25 | strength.min = QVariant(-500); 26 | strength.max = QVariant(500); 27 | strength.order = 2; 28 | configurables.insert("strength", strength); 29 | 30 | TextureGeneratorSetting offsetleft; 31 | offsetleft.name = "Offset left"; 32 | offsetleft.defaultvalue = QVariant((double) 0); 33 | offsetleft.min = QVariant(-100); 34 | offsetleft.max = QVariant(100); 35 | offsetleft.order = 3; 36 | configurables.insert("offsetleft", offsetleft); 37 | 38 | TextureGeneratorSetting offsettop; 39 | offsettop.name = "Offset top"; 40 | offsettop.defaultvalue = QVariant((double) 0); 41 | offsettop.min = QVariant(-100); 42 | offsettop.max = QVariant(100); 43 | offsettop.order = 4; 44 | configurables.insert("offsettop", offsettop); 45 | } 46 | 47 | 48 | void WhirlTextureGenerator::generate(QSize size, 49 | TexturePixel* destimage, 50 | QMap sourceimages, 51 | TextureNodeSettings* settings) const 52 | { 53 | if (!settings || !destimage || !size.isValid()) { 54 | return; 55 | } 56 | if (!sourceimages.contains(0)) { 57 | memset(destimage, 0, size.width() * size.height() * sizeof(TexturePixel)); 58 | return; 59 | } 60 | 61 | double radius = settings->value("radius").toDouble() * size.width() / 100; 62 | double strength = settings->value("strength").toDouble() / 80; 63 | double offsetleft = settings->value("offsetleft").toDouble() * size.width() / 100; 64 | double offsettop = settings->value("offsettop").toDouble() * size.height() / 100; 65 | 66 | TexturePixel* source = sourceimages.value(0)->getData(); 67 | int centerx = size.width() / 2 + offsetleft; 68 | int centery = size.height() / 2 + offsettop; 69 | 70 | for (int y = 0; y < size.height(); y++) { 71 | for (int x = 0; x < size.width(); x++) { 72 | double distortion = sqrt((x - centerx) * (x - centerx) + (y - centery) * (y - centery)); 73 | if (distortion > radius) { 74 | distortion = 0; 75 | } else { 76 | distortion = (radius - distortion) * (radius - distortion) / radius; 77 | } 78 | double angle = 2 * M_PI * distortion / (radius / strength); 79 | int xpos = ((x - centerx) * cos(angle)) - ((y - centery) * sin(angle)) + centerx; 80 | int ypos = ((y - centery) * cos(angle)) + ((x - centerx) * sin(angle)) + centery; 81 | xpos = xpos > size.height() ? xpos % size.height() : 82 | (xpos < 0 ? xpos + size.width() : xpos); 83 | ypos = ypos > size.height() ? ypos % size.height() : 84 | (ypos < 0 ? ypos + size.height() : ypos); 85 | xpos = qMax(qMin(xpos, size.width() - 1), 0); 86 | ypos = qMax(qMin(ypos, size.height() - 1), 0); 87 | destimage[y * size.width() + x] = source[ypos * size.width() + xpos]; 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /generators/whirl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef WHIRLTEXTUREGENERATOR_H 9 | #define WHIRLTEXTUREGENERATOR_H 10 | 11 | #include "texturegenerator.h" 12 | 13 | /** 14 | * @brief The WhirlTextureGenerator class 15 | */ 16 | class WhirlTextureGenerator : public TextureGenerator 17 | { 18 | public: 19 | WhirlTextureGenerator(); 20 | ~WhirlTextureGenerator() override = default; 21 | void generate(QSize size, 22 | TexturePixel* destimage, 23 | QMap sourceimages, 24 | TextureNodeSettings* settings) const override; 25 | int getNumSourceSlots() const override { return 1; } 26 | QString getName() const override { return QString("Whirl"); } 27 | const TextureGeneratorSettings& getSettings() const override { return configurables; } 28 | QString getDescription() const override { return QString("Twirls the image."); } 29 | TextureGenerator::Type getType() const override { return TextureGenerator::Type::Filter; } 30 | 31 | private: 32 | TextureGeneratorSettings configurables; 33 | }; 34 | 35 | #endif // WHIRLTEXTUREGENERATOR_H 36 | -------------------------------------------------------------------------------- /global.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXGENGLOBAL_H 9 | #define TEXGENGLOBAL_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * @brief The TexturePixel class 17 | * 18 | * 32 bit RGBA pixel, stored as BGRA. 19 | */ 20 | class TexturePixel { 21 | public: 22 | unsigned char b; 23 | unsigned char g; 24 | unsigned char r; 25 | unsigned char a; 26 | 27 | TexturePixel() = default; 28 | 29 | explicit 30 | TexturePixel(unsigned char red, unsigned char green, 31 | unsigned char blue, unsigned char alpha) 32 | : b(blue), g(green), r(red), a(alpha) {} 33 | 34 | TexturePixel(const TexturePixel& rhs) = default; 35 | 36 | /** 37 | * @brief TexturePixel::toRGBA 38 | * @return the pixel as RGBA 39 | */ 40 | quint32 toRGBA() const { 41 | quint32 ret = r; 42 | ret = ret << 8; 43 | ret += g; 44 | ret = ret << 8; 45 | ret += b; 46 | ret = ret << 8; 47 | ret += a; 48 | return ret; 49 | } 50 | 51 | TexturePixel& operator=(const TexturePixel& rhs) = default; 52 | 53 | TexturePixel& operator+=(const TexturePixel& rhs) { 54 | r = static_cast(qMin(static_cast(rhs.r) + static_cast(r), 255)); 55 | g = static_cast(qMin(static_cast(rhs.g) + static_cast(g), 255)); 56 | b = static_cast(qMin(static_cast(rhs.b) + static_cast(b), 255)); 57 | a = static_cast(qMin(static_cast(rhs.a) + static_cast(a), 255)); 58 | return *this; 59 | } 60 | 61 | TexturePixel operator+(const TexturePixel& rhs) const { 62 | TexturePixel ret(*this); 63 | ret += rhs; 64 | return ret; 65 | } 66 | 67 | /** 68 | * @brief TexturePixel::intensity 69 | * @return the intensity of pixel, from 0 - 1 70 | */ 71 | double intensity() const { 72 | return ((static_cast(this->r) + 73 | static_cast(this->g) + 74 | static_cast(this->b)) 75 | / 3.0) / 255.0; 76 | } 77 | 78 | /** 79 | * @brief TexturePixel::intensity 80 | * @return the intensity of pixel, from 0 - 1 81 | */ 82 | double intensityWithAlpha() const { 83 | return ((static_cast(this->r) + 84 | static_cast(this->g) + 85 | static_cast(this->b)) 86 | / 3.0) * this->a / 255.0; 87 | } 88 | 89 | }; 90 | 91 | 92 | struct TextureGeneratorSetting { 93 | QVariant defaultvalue; 94 | QString name; 95 | QString description = ""; 96 | int order = 0; 97 | int defaultindex = 0; // For QStringList 98 | QVariant min; 99 | QVariant max; 100 | QString group = ""; 101 | QString enabler = ""; 102 | }; 103 | 104 | typedef QMap TextureGeneratorSettings; 105 | 106 | typedef QMap TextureNodeSettings; 107 | 108 | #define ERROR_MSG(X) printf("ERROR: %s:%i: %s\n", __FUNCTION__, __LINE__, qPrintable(QString(X))) 109 | #define INFO_MSG(X) printf("INFO: %s: %s\n", __FUNCTION__, qPrintable(QString(X))) 110 | 111 | #endif // TEXGENGLOBAL_H 112 | -------------------------------------------------------------------------------- /gui/addnodepanel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef ADDNODEPANEL_H 9 | #define ADDNODEPANEL_H 10 | 11 | #include "generators/texturegenerator.h" 12 | #include 13 | #include 14 | 15 | class TextureProject; 16 | class QGridLayout; 17 | class QVBoxLayout; 18 | class QGroupBox; 19 | class QScrollArea; 20 | 21 | /** 22 | * @brief The AddNodePanel class 23 | * 24 | * Vertical panel that displays all available node types. 25 | * All generators are represented as buttons that can be dragged to 26 | * the scene to add a new node. 27 | * The button list is updated automatically when new generators are 28 | * added to the associated project. 29 | */ 30 | class AddNodePanel : public QWidget 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | explicit AddNodePanel(TextureProject*); 36 | ~AddNodePanel() override = default; 37 | 38 | public slots: 39 | void addGenerator(const TextureGeneratorPtr& generator); 40 | void removeGenerator(const TextureGeneratorPtr& generator); 41 | 42 | private: 43 | QMap widgets; 44 | TextureProject* project; 45 | QGroupBox* combinersWidget; 46 | QGroupBox* filtersWidget; 47 | QGroupBox* generatorsWidget; 48 | QGridLayout* filtersLayout; 49 | QGridLayout* combinersLayout; 50 | QGridLayout* generatorsLayout; 51 | }; 52 | 53 | 54 | #endif // ADDNODEPANEL_H 55 | -------------------------------------------------------------------------------- /gui/connectionwidget.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "base/textureproject.h" 9 | #include "gui/connectionwidget.h" 10 | #include "gui/iteminfopanel.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /** 17 | * @brief ConnectionWidget::ConnectionWidget 18 | * @param widgetmanager Parent. 19 | */ 20 | ConnectionWidget::ConnectionWidget(ItemInfoPanel* widgetmanager) 21 | { 22 | this->widgetmanager = widgetmanager; 23 | 24 | layout = new QVBoxLayout(this); 25 | this->setLayout(layout); 26 | 27 | nodeInfoWidget = new QGroupBox("Connection"); 28 | nodeInfoLayout = new QGridLayout(); 29 | nodeInfoWidget->setLayout(nodeInfoLayout); 30 | nodeSourceLabel = new QLabel(); 31 | nodeReceiverLabel = new QLabel(); 32 | nodeSlotLabel = new QLabel(); 33 | nodeInfoLayout->addWidget(new QLabel("Source: "), 0, 0); 34 | nodeInfoLayout->addWidget(new QLabel("Receiver: "), 1, 0); 35 | nodeInfoLayout->addWidget(new QLabel("Slot: "), 2, 0); 36 | nodeInfoLayout->addWidget(nodeSourceLabel, 0, 1); 37 | nodeInfoLayout->addWidget(nodeReceiverLabel, 1, 1); 38 | nodeInfoLayout->addWidget(nodeSlotLabel, 2, 1); 39 | layout->addWidget(nodeInfoWidget); 40 | 41 | QPushButton* disconnectNodesButton = new QPushButton("Disconnect"); 42 | layout->addWidget(disconnectNodesButton); 43 | QObject::connect(disconnectNodesButton, &QPushButton::clicked, 44 | this, &ConnectionWidget::disconnectNodes); 45 | 46 | auto* spaceritem = new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding); 47 | layout->addItem(spaceritem); 48 | 49 | sourceNodeId = -1; 50 | receiverNodeId = -1; 51 | slot = -1; 52 | } 53 | 54 | /** 55 | * @brief ConnectionWidget::disconnectNodes 56 | */ 57 | void ConnectionWidget::disconnectNodes() 58 | { 59 | TextureProject* project = widgetmanager->getTextureProject(); 60 | if (project == nullptr) { 61 | return; 62 | } 63 | TextureNodePtr node = project->getNode(receiverNodeId); 64 | if (node.isNull()) { 65 | return; 66 | } 67 | node.data()->setSourceSlot(slot, 0); 68 | this->hide(); 69 | } 70 | 71 | /** 72 | * @brief ConnectionWidget::setNodes 73 | * @param sourceNodeId Source node id 74 | * @param receiverNodeId Receiver node id 75 | * @param slot Receiver's slot id 76 | * 77 | * Updates the widget to display a new connection. Called when the user selects 78 | * a different connection (so that we don't need to create a new widget for 79 | * every single connection). 80 | */ 81 | void ConnectionWidget::setNodes(int sourceNodeId, int receiverNodeId, int slot) 82 | { 83 | this->sourceNodeId = sourceNodeId; 84 | this->receiverNodeId = receiverNodeId; 85 | this->slot = slot; 86 | 87 | nodeSourceLabel->setText(QString("%1").arg(sourceNodeId)); 88 | nodeReceiverLabel->setText(QString("%1").arg(receiverNodeId)); 89 | nodeSlotLabel->setText(QString("%1").arg(slot + 1)); 90 | 91 | TextureProject* project = widgetmanager->getTextureProject(); 92 | if (project != nullptr) { 93 | TextureNodePtr node; 94 | node = project->getNode(sourceNodeId); 95 | if (!node.isNull()) { 96 | nodeSourceLabel->setText(QString("%1\n(%2)") 97 | .arg(node->getName(), node->getGeneratorName())); 98 | } 99 | node = project->getNode(receiverNodeId); 100 | if (!node.isNull()) { 101 | nodeReceiverLabel->setText(QString("%1\n(%2)") 102 | .arg(node->getName(), node->getGeneratorName())); 103 | } 104 | } 105 | } 106 | 107 | 108 | -------------------------------------------------------------------------------- /gui/connectionwidget.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef CONNECTIONWIDGET_H 9 | #define CONNECTIONWIDGET_H 10 | 11 | #include 12 | 13 | class TextureProject; 14 | class ItemInfoPanel; 15 | class QLabel; 16 | class QVBoxLayout; 17 | class QGroupBox; 18 | class QGridLayout; 19 | 20 | /** 21 | * @brief The ConnectionWidget class 22 | * 23 | * Simple widget that displays a connections. Currently just lists 24 | * the names of the source and receiver nodes with a button for 25 | * disconnecting them. 26 | * 27 | * @todo Display the nodes' images similar to PreviewImagePanel 28 | */ 29 | class ConnectionWidget : public QWidget 30 | { 31 | Q_OBJECT 32 | 33 | public: 34 | explicit ConnectionWidget(ItemInfoPanel* widgetmanager); 35 | ~ConnectionWidget() override = default; 36 | void setNodes(int sourceNodeId, int receiverNodeId, int slot); 37 | 38 | public slots: 39 | void disconnectNodes(); 40 | 41 | private: 42 | ItemInfoPanel* widgetmanager; 43 | int sourceNodeId; 44 | int receiverNodeId; 45 | int slot; 46 | 47 | QGroupBox* nodeInfoWidget; 48 | QGridLayout* nodeInfoLayout; 49 | QLabel* nodeSourceLabel; 50 | QLabel* nodeReceiverLabel; 51 | QLabel* nodeSlotLabel; 52 | QVBoxLayout* layout; 53 | }; 54 | 55 | #endif // CONNECTIONWIDGET_H 56 | -------------------------------------------------------------------------------- /gui/cubewidget.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef PREVIEW3DPANEL_H 9 | #define PREVIEW3DPANEL_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /** 21 | * @brief The CubeWidget class 22 | */ 23 | class CubeWidget : public QOpenGLWidget, protected QOpenGLFunctions 24 | { 25 | Q_OBJECT 26 | struct VertexData { 27 | QVector3D position; 28 | QVector2D texCoord; 29 | }; 30 | 31 | public: 32 | explicit CubeWidget(QWidget *parent = nullptr); 33 | ~CubeWidget() override; 34 | void setTexture(const QPixmap& pixmap); 35 | 36 | public slots: 37 | void imageUpdated(); 38 | void setBackgroundColor(const QColor& color); 39 | 40 | protected: 41 | void mousePressEvent(QMouseEvent *e) override; 42 | void mouseReleaseEvent(QMouseEvent *e) override; 43 | void timerEvent(QTimerEvent *e) override; 44 | void initializeGL() override; 45 | void resizeGL(int width, int height) override; 46 | void paintGL() override; 47 | void initShaders(); 48 | 49 | private: 50 | QBasicTimer timer; 51 | QOpenGLShaderProgram program; 52 | QOpenGLTexture* texture; 53 | bool textureUpdated; 54 | QMatrix4x4 projection; 55 | QVector2D mousePressPosition; 56 | QVector3D rotationAxis; 57 | double angularSpeed; 58 | QQuaternion rotation; 59 | bool textureAvailable; 60 | QOpenGLBuffer arrayBuf; 61 | QOpenGLBuffer indexBuf; 62 | QColor backgroundcolor; 63 | bool initialized; 64 | }; 65 | 66 | 67 | #endif // PREVIEW3DPANEL_H 68 | -------------------------------------------------------------------------------- /gui/iteminfopanel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef ITEMINFOPANEL_H 9 | #define ITEMINFOPANEL_H 10 | 11 | #include "base/texturenode.h" 12 | #include 13 | #include 14 | #include 15 | 16 | class TextureProject; 17 | class NodeSettingsWidget; 18 | class ConnectionWidget; 19 | class SceneInfoWidget; 20 | 21 | /** 22 | * @brief The ItemInfoPanel class 23 | * 24 | * Controls which info widget to display at a given moment. Either the scene node, 25 | * when no node is selected in the graph, the node settings widget or the line 26 | * node connection info widget. 27 | */ 28 | class ItemInfoPanel : public QWidget 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | ItemInfoPanel(QWidget* parent, TextureProject* textureProject); 34 | ~ItemInfoPanel() override = default; 35 | TextureProject* getTextureProject() { return texproject; } 36 | 37 | public slots: 38 | void setActiveNode(int id); 39 | void setActiveLine(int sourceNodeId, int receiverNodeId, int slot); 40 | void removeNode(int id); 41 | void addNode(const TextureNodePtr&); 42 | void sourceUpdated(int id); 43 | void nodesDisconnected(int sourceNodeId, int receiverNodeId, int slot); 44 | 45 | private: 46 | TextureProject* texproject; 47 | QMap nodes; 48 | 49 | ConnectionWidget* lineWidget; 50 | NodeSettingsWidget* currWidget; 51 | SceneInfoWidget* sceneWidget; 52 | int currNodeId; 53 | std::tuple currLine; 54 | }; 55 | 56 | 57 | #endif // ITEMINFOPANEL_H 58 | -------------------------------------------------------------------------------- /gui/mainwindow.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef MAINWINDOW_H 9 | #define MAINWINDOW_H 10 | 11 | #include "generators/texturegenerator.h" 12 | #include 13 | 14 | class TexGenApplication; 15 | class TextureProject; 16 | class ViewNodeScene; 17 | class ViewNodeView; 18 | class ItemInfoPanel; 19 | class AddNodePanel; 20 | class QCloseEvent; 21 | class MenuActions; 22 | class PreviewImagePanel; 23 | class Preview3dPanel; 24 | class SettingsPanel; 25 | class SettingsManager; 26 | class JSTexGenManager; 27 | 28 | /** 29 | * @brief The MainWindow class 30 | * 31 | * The application's main window, containing all the scenes and panels. 32 | * 33 | * It initializes and configures the TextureProject with its submodules, 34 | * including which texture generators should be loaded. 35 | */ 36 | class MainWindow : public QMainWindow 37 | { 38 | Q_OBJECT 39 | 40 | public: 41 | explicit MainWindow(TexGenApplication* parent = nullptr); 42 | ~MainWindow() override; 43 | TextureProject* getTextureProject() { return project; } 44 | TexGenApplication* parent() { return parentapp; } 45 | MenuActions* getMenu() { return menuactions; } 46 | 47 | public slots: 48 | bool saveAs(); 49 | bool saveFile(bool newFileName = false); 50 | void openFile(const QString&); 51 | void clearScene(); 52 | void showAbout(); 53 | void showHelp(); 54 | void closeEvent(QCloseEvent*) override; 55 | void copyNode(); 56 | void pasteNode(); 57 | void cutNode(); 58 | void saveImage(int id = 0); 59 | void reloadSceneView(); 60 | void moveToFront(); 61 | void resetViewZoom(); 62 | void generatorNameCollision(const TextureGeneratorPtr&, const TextureGeneratorPtr&); 63 | 64 | private: 65 | void drawScene(); 66 | void createActions(); 67 | bool maybeSave(); 68 | ViewNodeScene* createScene(ViewNodeScene* source = nullptr); 69 | 70 | TexGenApplication* parentapp; 71 | TextureProject* project; 72 | QString savedFileName; 73 | MenuActions* menuactions; 74 | 75 | ViewNodeScene* scene; 76 | ViewNodeView* view; 77 | SettingsManager* settingsManager; 78 | JSTexGenManager* jstexgenManager; 79 | ItemInfoPanel* iteminfopanel; 80 | SettingsPanel* settingspanel; 81 | AddNodePanel* addnodewidget; 82 | PreviewImagePanel* previewimagewidget; 83 | Preview3dPanel* preview3dwidget; 84 | }; 85 | 86 | #endif // MAINWINDOW_H 87 | -------------------------------------------------------------------------------- /gui/menuactions.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef MENUACTIONS_H 9 | #define MENUACTIONS_H 10 | 11 | #include 12 | #include 13 | 14 | class QMainWindow; 15 | class TextureProject; 16 | class TextureGenerator; 17 | class QMenu; 18 | class QAction; 19 | class MainWindow; 20 | class AddNodePanel; 21 | class PreviewImagePanel; 22 | class Preview3dPanel; 23 | class ItemInfoPanel; 24 | class SettingsPanel; 25 | class QToolBar; 26 | 27 | /** 28 | * @brief The MenuActions class 29 | * 30 | * Sets up the MainWindow's menus and toolbars and 31 | * the respective actions. 32 | * 33 | * Upon destruction the panel and toolbar visiblity settings are written 34 | * to persistant storage and loaded the next time the application is started. 35 | */ 36 | class MenuActions : public QObject 37 | { 38 | Q_OBJECT 39 | 40 | public: 41 | explicit MenuActions(MainWindow* parentwindow); 42 | MainWindow* parent() { return parentwindow; } 43 | ~MenuActions() override; 44 | void setAddNodePanel(AddNodePanel* addNodePanel); 45 | void setPreviewImagePanel(PreviewImagePanel* previewImagePanel); 46 | void setSettingsPanel(SettingsPanel* settingsPanel); 47 | void setItemInfoPanel(ItemInfoPanel* settingswidget); 48 | 49 | public slots: 50 | void toggleAddNodePanel(); 51 | void togglePreviewImagePanel(); 52 | void toggleItemInfoPanel(); 53 | void toggleSettingsPanel(); 54 | void toogleToolbars(); 55 | void openFile(); 56 | void windowsChanged(); 57 | 58 | private: 59 | MainWindow* parentwindow; 60 | AddNodePanel* nodepanel; 61 | PreviewImagePanel* previewImagePanel; 62 | ItemInfoPanel* nodesettings; 63 | SettingsPanel* settingspanel; 64 | 65 | QToolBar* settingsToolBar; 66 | QToolBar* fileToolBar; 67 | QToolBar* editToolBar; 68 | QToolBar* insertToolBar; 69 | QToolBar* toggleAddNodeToolBar; 70 | 71 | QMenu* fileMenu; 72 | QMenu* viewMenu; 73 | QMenu* editMenu; 74 | QMenu* helpMenu; 75 | 76 | QAction* newAct; 77 | QAction* openAct; 78 | QAction* saveAct; 79 | QAction* saveAsAct; 80 | QAction* saveImageAct; 81 | QAction* closeAct; 82 | QAction* exitAct; 83 | QAction* clearAct; 84 | QAction* copyAct; 85 | QAction* cutAct; 86 | QAction* pasteAct; 87 | QAction* helpAct; 88 | QAction* aboutAct; 89 | QAction* resetZoomAct; 90 | QAction* resetSceneAct; 91 | QAction* displayAddNodePanelAct; 92 | QAction* displayPreviewImagePanelAct; 93 | QAction* displayPreview3dPanelAct; 94 | QAction* displayItemInfoPanelAct; 95 | QAction* displaySettingsPanelAct; 96 | QAction* displayToolbarsAct; 97 | QAction* toggleItemInfoPanelAct; 98 | QAction* togglePreviewImagePanelAct; 99 | QAction* togglePreview3dPanelAct; 100 | QAction* toggleAddNodePanelAct; 101 | 102 | QVector windowlistActions; 103 | QString lastOpenedDirectory; 104 | }; 105 | 106 | #endif // MENUACTIONS_H 107 | -------------------------------------------------------------------------------- /gui/nodesettingswidget.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef NODESETTINGSWIDGET_H 9 | #define NODESETTINGSWIDGET_H 10 | 11 | #include "base/texturenode.h" 12 | #include 13 | #include 14 | #include 15 | 16 | class ItemInfoPanel; 17 | class QLabel; 18 | class QPushButton; 19 | class QSpacerItem; 20 | class QGroupBox; 21 | class QLineEdit; 22 | class QFormLayout; 23 | class QSlider; 24 | class QGridLayout; 25 | class QDoubleSlider; 26 | class QScrollArea; 27 | class QVBoxLayout; 28 | 29 | /** 30 | * @brief The NodeSettingsWidget class 31 | * 32 | * Vertical panel for changing the values sent to the node's generator. 33 | * Has widgets for displaying and setting integer, double, color and 34 | * string/enum values. 35 | */ 36 | class NodeSettingsWidget : public QWidget 37 | { 38 | Q_OBJECT 39 | 40 | public: 41 | NodeSettingsWidget(ItemInfoPanel* widgetmanager, int id); 42 | ~NodeSettingsWidget() override = default; 43 | 44 | public slots: 45 | void settingsUpdated(); 46 | void slotsUpdated(); 47 | void generatorUpdated(); 48 | void saveSettings(); 49 | void colorDialog(const QString&); 50 | void swapSlots(); 51 | 52 | private: 53 | QFormLayout* createGroupLayout(); 54 | void styleButton(QPushButton* button, const QColor& color); 55 | void setGroupAlignment(const QString& group, bool aligned); 56 | ItemInfoPanel* widgetmanager; 57 | int id; 58 | TextureNodePtr texNode; 59 | bool saveDisabled; 60 | 61 | QMap settingLabels; 62 | QMap settingElements; 63 | QMap settingSliders; 64 | QMap settingValues; 65 | 66 | QScrollArea* scrollarea; 67 | QWidget* contents; 68 | QVBoxLayout* contentsLayout; 69 | 70 | QFormLayout* settingsLayout; 71 | QGroupBox* settingsWidget; 72 | 73 | QLabel* generatorNameLabel; 74 | QGroupBox* nodeInfoWidget; 75 | QFormLayout* nodeInfoLayout; 76 | QLineEdit* nodeNameLineEdit; 77 | 78 | QGroupBox* sourceButtonsWidget; 79 | QGridLayout* sourceButtonsLayout; 80 | QList sourceSlotLabels; 81 | QPushButton* swapSlotButton; 82 | QList sourceSlotButtons; 83 | QVBoxLayout* layout; 84 | }; 85 | 86 | #endif // NODESETTINGSWIDGET_H 87 | -------------------------------------------------------------------------------- /gui/previewimagepanel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef PREVIEWIMAGEPANEL_H 9 | #define PREVIEWIMAGEPANEL_H 10 | 11 | #include 12 | 13 | class TextureProject; 14 | class QGridLayout; 15 | class QVBoxLayout; 16 | class QGroupBox; 17 | class QPushButton; 18 | class ImageLabel; 19 | class QLabel; 20 | class QComboBox; 21 | class CubeWidget; 22 | class QResizeEvent; 23 | class QShowEvent; 24 | 25 | /** 26 | * @brief The PreviewImagePanel class 27 | * 28 | * Vertical panel that displays a node's generated image. 29 | * When an active node's image is updated this also propagates 30 | * to the panel, which then updates the displayed image. 31 | */ 32 | class PreviewImagePanel : public QWidget 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | explicit PreviewImagePanel(TextureProject*); 38 | ~PreviewImagePanel() override = default; 39 | void showEvent(QShowEvent* event) override; 40 | bool loadNodeImage(int); 41 | 42 | public slots: 43 | void setActiveNode(int); 44 | void imageAvailable(int, QSize); 45 | void imageUpdated(int); 46 | void settingsUpdated(); 47 | void nodeRemoved(int); 48 | 49 | private: 50 | QPixmap tilePixmap(const QPixmap& pixmap, int number); 51 | TextureProject* project; 52 | QVBoxLayout* layout; 53 | QComboBox* combobox; 54 | ImageLabel* imageLabel; 55 | CubeWidget* cubeWidget; 56 | QPushButton* lockNodeButton; 57 | int currId; 58 | int numTiles; 59 | QSize imageSize; 60 | }; 61 | 62 | /** 63 | * @brief The ImageLabel class 64 | * 65 | * QLabel with added functions to handle automatic 66 | * scaling of QPixmap images to fit them in inside a QWidget. 67 | * Supports 2x2 tiled drawing. 68 | */ 69 | class ImageLabel : public QWidget 70 | { 71 | Q_OBJECT 72 | public: 73 | explicit ImageLabel(QWidget* parent = nullptr); 74 | public slots: 75 | void setPixmap(const QPixmap&); 76 | protected: 77 | void resizeEvent(QResizeEvent*) override; 78 | private slots: 79 | void resizeImage(); 80 | private: 81 | QLabel* label; 82 | }; 83 | 84 | #endif // PREVIEWIMAGEPANEL_H 85 | -------------------------------------------------------------------------------- /gui/qdoubleslider.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef QDOUBLESLIDER_H 9 | #define QDOUBLESLIDER_H 10 | 11 | #include 12 | 13 | /** 14 | * @brief The QDoubleSlider class 15 | * 16 | * Class derived from QSlider to support floating point values. 17 | * QSlider only supports integers so this has been modified to refer to the values 18 | * in 0,01 increments (100 times the value). 19 | * All signals and slots upscales or downscales it so that it can be used 20 | * interchangeably as a replacement for QSlider. 21 | */ 22 | class QDoubleSlider : public QSlider { 23 | Q_OBJECT 24 | 25 | public: 26 | explicit QDoubleSlider(Qt::Orientation orientation = Qt::Orientation::Horizontal, QWidget* parent = nullptr) 27 | : QSlider(orientation, parent) { 28 | QObject::connect(this, &QDoubleSlider::valueChanged, 29 | this, &QDoubleSlider::notifyValueChanged); 30 | } 31 | 32 | signals: 33 | void doubleValueChanged(double value); 34 | 35 | public slots: 36 | void setDoubleMinimum(double value) { 37 | setMinimum(value * 100); 38 | } 39 | void setDoubleMaximum(double value) { 40 | setMaximum(value * 100); 41 | } 42 | void notifyValueChanged(int value) { 43 | emit doubleValueChanged((double) value / 100.0); 44 | } 45 | void setDoubleValue(double value) { 46 | setValue(value * 100); 47 | } 48 | }; 49 | 50 | #endif // QDOUBLESLIDER_H 51 | -------------------------------------------------------------------------------- /gui/sceneinfowidget.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "base/textureproject.h" 9 | #include "gui/iteminfopanel.h" 10 | #include "gui/sceneinfowidget.h" 11 | #include 12 | #include 13 | 14 | /** 15 | * @brief SceneInfoWidget::SceneInfoWidget 16 | * @param widgetmanager Parent 17 | */ 18 | SceneInfoWidget::SceneInfoWidget(ItemInfoPanel* widgetmanager) 19 | { 20 | this->widgetmanager = widgetmanager; 21 | 22 | layout = new QVBoxLayout(this); 23 | this->setLayout(layout); 24 | 25 | nodeInfoWidget = new QGroupBox("Scene info"); 26 | nodeInfoLayout = new QGridLayout(); 27 | nodeInfoWidget->setLayout(nodeInfoLayout); 28 | nodeInfoLayout->addWidget(new QLabel("Number of nodes: "), 0, 0); 29 | numNodesLabel = new QLabel("0", this); 30 | nodeInfoLayout->addWidget(numNodesLabel, 0, 1); 31 | layout->addWidget(nodeInfoWidget); 32 | 33 | layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); 34 | } 35 | 36 | /** 37 | * @brief SceneInfoWidget::updateNumNodes 38 | * Updates the text label with the number of nodes. 39 | */ 40 | void SceneInfoWidget::updateNumNodes() 41 | { 42 | int num = widgetmanager->getTextureProject()->getNumNodes(); 43 | numNodesLabel->setText(QString("%1").arg(num)); 44 | } 45 | -------------------------------------------------------------------------------- /gui/sceneinfowidget.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SCENEINFOWIDGET_H 9 | #define SCENEINFOWIDGET_H 10 | 11 | #include "base/texturenode.h" 12 | #include 13 | #include 14 | 15 | class ItemInfoPanel; 16 | class QLabel; 17 | class QGroupBox; 18 | class QVBoxLayout; 19 | 20 | /** 21 | * @brief The SceneInfoWidget class 22 | * 23 | * Simple widget which currently just displays the number of nodes 24 | * in the scene. For having something to display in the info panel 25 | * when the scene's empty. 26 | */ 27 | class SceneInfoWidget : public QWidget 28 | { 29 | Q_OBJECT 30 | 31 | public: 32 | explicit SceneInfoWidget(ItemInfoPanel* widgetmanager); 33 | ~SceneInfoWidget() override = default; 34 | void updateNumNodes(); 35 | 36 | private: 37 | ItemInfoPanel* widgetmanager; 38 | 39 | QGroupBox* nodeInfoWidget; 40 | QGridLayout* nodeInfoLayout; 41 | QLabel* numNodesLabel; 42 | QVBoxLayout* layout; 43 | }; 44 | 45 | #endif // SCENEINFOWIDGET_H 46 | -------------------------------------------------------------------------------- /gui/settingspanel.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef SETTINGSPANEL_H 9 | #define SETTINGSPANEL_H 10 | 11 | #include 12 | 13 | class QVBoxLayout; 14 | class QScrollArea; 15 | class QSpinBox; 16 | class SettingsManager; 17 | class QLineEdit; 18 | class QCheckBox; 19 | class QPushButton; 20 | class MainWindow; 21 | class QComboBox; 22 | 23 | /** 24 | * @brief The SettingsPanel class 25 | * 26 | * Vertical panel with all the user controlled settings for a project 27 | * listed. Connected to a SettingsManager instance which loads and saved 28 | * to an persistant storage. 29 | */ 30 | class SettingsPanel : public QWidget 31 | { 32 | Q_OBJECT 33 | 34 | public: 35 | SettingsPanel(MainWindow* parent, SettingsManager* settingsmanager); 36 | ~SettingsPanel() override = default; 37 | void showEvent(QShowEvent*) override; 38 | 39 | public slots: 40 | void settingsUpdated(); 41 | void saveSettings(); 42 | void selectDirectoryPath(QLineEdit*); 43 | void colorDialog(QPushButton*); 44 | 45 | private: 46 | void styleColorButton(QPushButton*, const QColor&); 47 | 48 | SettingsManager* settingsmanager; 49 | 50 | QVBoxLayout* contentsLayout; 51 | QVBoxLayout* layout; 52 | QScrollArea* area; 53 | QWidget* contents; 54 | 55 | QSpinBox* thumbnailWidthSpinbox; 56 | QSpinBox* thumbnailHeightSpinbox; 57 | QSpinBox* exportImageWidthSpinbox; 58 | QSpinBox* exportImageHeightSpinbox; 59 | QSpinBox* defaultZoomSpinbox; 60 | QLineEdit* jsGeneratorPathEdit; 61 | QCheckBox* jsGeneratorEnabledCheckbox; 62 | QPushButton* backgroundColorButton; 63 | QPushButton* previewBackgroundColorButton; 64 | QComboBox* backgroundBrushCombobox; 65 | 66 | bool blockSlot; 67 | }; 68 | 69 | #endif // SETTINGSPANEL_H 70 | -------------------------------------------------------------------------------- /images/copyicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/copyicon.png -------------------------------------------------------------------------------- /images/cuticon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/cuticon.png -------------------------------------------------------------------------------- /images/mainicon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/mainicon.icns -------------------------------------------------------------------------------- /images/mainicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/mainicon.ico -------------------------------------------------------------------------------- /images/mainicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/mainicon.png -------------------------------------------------------------------------------- /images/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/new.png -------------------------------------------------------------------------------- /images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/open.png -------------------------------------------------------------------------------- /images/pasteicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/pasteicon.png -------------------------------------------------------------------------------- /images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanokl/ProceduralTextureMaker/1d46e273b5e213ad15c635233b4e7763d5404be4/images/save.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "texgenapplication.h" 9 | #include 10 | 11 | int main(int argc, char**argv) 12 | { 13 | QCoreApplication::setOrganizationName("Johan Lindqvist"); 14 | QCoreApplication::setOrganizationDomain("github.com/johanokl"); 15 | QCoreApplication::setApplicationName("ProceduralTextureMaker"); 16 | 17 | TexGenApplication app(argc, argv); 18 | return app.exec(); 19 | } 20 | -------------------------------------------------------------------------------- /sceneview/viewnodeitem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef VIEWNODEITEM_H 9 | #define VIEWNODEITEM_H 10 | 11 | #include "base/texturenode.h" 12 | #include 13 | 14 | class ViewNodeScene; 15 | class TextureNode; 16 | class ViewNodeLine; 17 | 18 | /** 19 | * @brief The ViewNodeItem class 20 | * 21 | * Renders the node as a widget in a ViewNodeView scene. 22 | * Contains functions that let the user interact with the node and 23 | * change connections, positions etc. 24 | */ 25 | class ViewNodeItem : public QGraphicsItem 26 | { 27 | friend class ViewNodeLine; 28 | friend class ViewNodeScene; 29 | 30 | public: 31 | ViewNodeItem(ViewNodeScene* scene, const TextureNodePtr& newNode); 32 | ~ViewNodeItem() override = default; 33 | void paint (QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; 34 | int getId() const { return id; } 35 | TextureNodePtr getTextureNode() { return texNode; } 36 | bool posInImage(QPointF pos) const; 37 | QRectF boundingRect() const override; 38 | QPainterPath shape() const override; 39 | QVariant itemChange(GraphicsItemChange change, const QVariant& value) override; 40 | void showConnectable(bool showConnectable); 41 | void showUnconnectable(bool showUnconnectable); 42 | void clearOverlays(); 43 | QSet getStartLines() const { return startLines; } 44 | QMap getEndLines() const { return endLines; } 45 | void addConnectionLine(ViewNodeLine* line); 46 | void removeConnectionLine(ViewNodeLine* line); 47 | 48 | public slots: 49 | void positionUpdated(); 50 | void settingsUpdated(); 51 | void imageUpdated(); 52 | void imageAvailable(QSize size); 53 | void generatorUpdated(); 54 | void setThumbnailSize(QSize); 55 | 56 | protected: 57 | void mousePressEvent(QGraphicsSceneMouseEvent* event) override; 58 | void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 59 | void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override; 60 | void hoverMoveEvent(QGraphicsSceneHoverEvent* event) override; 61 | void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 62 | void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 63 | void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; 64 | 65 | private: 66 | int id; 67 | 68 | ViewNodeScene* scene; 69 | QPixmap pixmap; 70 | TextureNodePtr texNode; 71 | QSize thumbnailSize; 72 | QString titleString; 73 | 74 | int highlightSlot; 75 | QPointF mousePressedPos; 76 | QPointF mousePressedItemPos; 77 | int highlighterWidth; 78 | int borderWidth; 79 | 80 | QSet startLines; 81 | QMap endLines; 82 | 83 | bool imageValid; 84 | bool isUnconnectable; 85 | bool isConnectable; 86 | bool mousePressed; 87 | }; 88 | 89 | #endif // VIEWNODEITEM_H 90 | -------------------------------------------------------------------------------- /sceneview/viewnodeline.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef VIEWNODELINE_H 9 | #define VIEWNODELINE_H 10 | 11 | #include 12 | 13 | class ViewNodeItem; 14 | class ViewNodeScene; 15 | class QPen; 16 | 17 | /** 18 | * @brief The ViewNodeLine class 19 | * 20 | * Draws a styled line in a ViewNodeScene. 21 | */ 22 | class ViewNodeLine : public QGraphicsLineItem 23 | { 24 | friend class ViewNodeScene; 25 | friend class ViewNodeItem; 26 | 27 | public: 28 | ~ViewNodeLine() override; 29 | void updatePos(); 30 | inline int getSlot() const { return slot; } 31 | inline int getStartItemId() const { return sourceItemId; } 32 | inline int getEndItemId() const { return receiverItemId; } 33 | void setHighlighted(bool highlighted); 34 | void setWidth(int width); 35 | void setColor(const QColor& color); 36 | void setNodes(int sourceNodeId, int receiverNodeId); 37 | void setPos(QPointF startPos, QPointF endPos); 38 | QRectF boundingRect() const override; 39 | QPainterPath shape() const override; 40 | 41 | protected: 42 | void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; 43 | void mousePressEvent(QGraphicsSceneMouseEvent* event) override; 44 | void hoverEnterEvent(QGraphicsSceneHoverEvent* event) override; 45 | void hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override; 46 | 47 | private: 48 | ViewNodeLine(ViewNodeScene* scene, int sourceItem, int receiverItem, int slot); 49 | ViewNodeScene* nodescene; 50 | int sourceItemId; 51 | int receiverItemId; 52 | int slot; 53 | 54 | QPointF sourcePos; 55 | QPointF receiverPos; 56 | 57 | QPolygonF arrowHead; 58 | QPen* myPen; 59 | bool infocus; 60 | }; 61 | 62 | #endif // VIEWNODELINE_H 63 | -------------------------------------------------------------------------------- /sceneview/viewnodescene.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef VIEWNODESCENE_H 9 | #define VIEWNODESCENE_H 10 | 11 | #include "base/texturenode.h" 12 | #include 13 | #include 14 | #include 15 | 16 | class TextureProject; 17 | class ViewNodeItem; 18 | class ViewNodeLine; 19 | class TextureGenerator; 20 | class MainWindow; 21 | class QAction; 22 | class QGraphicsRectItem; 23 | 24 | /** 25 | * @brief The ViewNodeScene class 26 | * 27 | * The visualization of a TextureProject node scene. 28 | * 29 | * Manages the ViewNodeItem and ViewNodeLine object as well as 30 | * user's actions on it via the scene widget. 31 | */ 32 | class ViewNodeScene : public QGraphicsScene 33 | { 34 | Q_OBJECT 35 | friend class ViewNodeItem; 36 | 37 | public: 38 | explicit ViewNodeScene(MainWindow* parent); 39 | ~ViewNodeScene() override = default; 40 | ViewNodeScene* clone() const; 41 | TextureProject* getTextureProject() const { return project; } 42 | MainWindow* getParent() const { return parent; } 43 | virtual void clear(); 44 | void endLineDrawing(int endNode); 45 | void startLineDrawing(int nodeId); 46 | ViewNodeItem* getItem(int id) const; 47 | 48 | void setSelectedNode(int id); 49 | int getSelectedNode() const { return selectedNode; } 50 | void setSelectedLine(int sourceNode, int receiverNode, int slot); 51 | void connectNodes(int sourceNodeId, int receiverNodeId, int slotId); 52 | void removeConnection(int sourceNodeId, int receiverNodeId); 53 | 54 | protected: 55 | void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 56 | void mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 57 | void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 58 | void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override; 59 | void dragEnterEvent(QGraphicsSceneDragDropEvent* event) override; 60 | void dragMoveEvent(QGraphicsSceneDragDropEvent* event) override; 61 | void dragLeaveEvent(QGraphicsSceneDragDropEvent* event) override; 62 | void dropEvent(QGraphicsSceneDragDropEvent* event) override; 63 | void keyPressEvent(QKeyEvent* event) override; 64 | 65 | public slots: 66 | void addNode(const TextureNodePtr& newNode); 67 | void nodeRemoved(int id); 68 | void positionUpdated(int id); 69 | void nodeSettingsUpdated(int id); 70 | void imageUpdated(int id); 71 | void imageAvailable(int id, QSize size); 72 | void nodesConnected(int sourceid, int slot, int receiverid); 73 | void nodesDisconnected(int sourceid, int slot, int receiverid); 74 | void generatorUpdated(int id); 75 | void settingsUpdated(); 76 | 77 | signals: 78 | void nodeSelected(int id); 79 | void lineSelected(int sourceNode, int receiverNode, int slot); 80 | 81 | private: 82 | MainWindow* parent; 83 | TextureProject* project; 84 | QMap nodeItems; 85 | QMap, ViewNodeLine*> nodeConnections; 86 | 87 | QGraphicsRectItem* dropItem; 88 | ViewNodeLine* lineItem; 89 | int startLineNode; 90 | int selectedNode; 91 | std::tuple selectedLine; 92 | bool lineDrawing; 93 | }; 94 | 95 | #endif // VIEWNODESCENE_H 96 | -------------------------------------------------------------------------------- /sceneview/viewnodeview.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "viewnodeview.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | /** 16 | * @brief ViewNodeView::ViewNodeView 17 | * @param defaultzoom Zoom factor in percentage, 100 is 1:1. 18 | */ 19 | ViewNodeView::ViewNodeView(int defaultzoom) 20 | { 21 | setMouseTracking(true); 22 | // The mouse wheel scroll factor 23 | scrollZoomFactor = 1.0015; 24 | setDragMode(QGraphicsView::ScrollHandDrag); 25 | defaultZoomFactor = static_cast(defaultzoom) / 100; 26 | scale(defaultZoomFactor, defaultZoomFactor); 27 | } 28 | 29 | /** 30 | * @brief ViewNodeView::setDefaultZoom 31 | * @param zoom Zoom factor in percentage, 100 is 1:1. 32 | */ 33 | void ViewNodeView::setDefaultZoom(int zoom) 34 | { 35 | defaultZoomFactor = static_cast(zoom) / 100; 36 | resetZoom(); 37 | } 38 | 39 | /** 40 | * @brief ViewNodeView::resetZoom 41 | * Resets to the default zoom, 100%. 42 | */ 43 | void ViewNodeView::resetZoom() 44 | { 45 | const ViewportAnchor anchor = transformationAnchor(); 46 | setTransformationAnchor(QGraphicsView::AnchorViewCenter); 47 | resetTransform(); 48 | scale(defaultZoomFactor, defaultZoomFactor); 49 | setTransformationAnchor(anchor); 50 | } 51 | 52 | /** 53 | * @brief ViewNodeView::wheelEvent 54 | * @param event 55 | * 56 | * Zooms in and out from the screen when the user scrolls the 57 | * mouse wheel while pressing the Shift or Alt keys. 58 | */ 59 | void ViewNodeView::wheelEvent(QWheelEvent* event) { 60 | auto* wheel_event = static_cast(event); 61 | if (QApplication::keyboardModifiers() == Qt::ShiftModifier 62 | || QApplication::keyboardModifiers() == Qt::AltModifier) { 63 | const ViewportAnchor anchor = transformationAnchor(); 64 | setTransformationAnchor(QGraphicsView::AnchorUnderMouse); 65 | double angle = wheel_event->angleDelta().y(); 66 | double factor = qPow(scrollZoomFactor, angle); 67 | scale(factor, factor); 68 | setTransformationAnchor(anchor); 69 | } 70 | QGraphicsView::wheelEvent(event); 71 | } 72 | -------------------------------------------------------------------------------- /sceneview/viewnodeview.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef VIEWNODEVIEW_H 9 | #define VIEWNODEVIEW_H 10 | 11 | #include 12 | #include 13 | 14 | /** 15 | * @brief The ViewNodeView class 16 | * 17 | * Displays a ViewNodeScene instance with ViewNodeItem/ViewNodeLine objects. 18 | * Supports zooming and scrolling, both with mouse dragging and scrollbars. 19 | */ 20 | class ViewNodeView : public QGraphicsView 21 | { 22 | public: 23 | explicit ViewNodeView(int defaultZoom = 100); 24 | ~ViewNodeView() override = default; 25 | 26 | public slots: 27 | void resetZoom(); 28 | void setDefaultZoom(int zoom); 29 | 30 | protected: 31 | void wheelEvent(QWheelEvent* event) override; 32 | 33 | private: 34 | double scrollZoomFactor; 35 | double defaultZoomFactor; 36 | }; 37 | 38 | #endif // VIEWNODEVIEW_H 39 | -------------------------------------------------------------------------------- /shaders.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3d/vshader.glsl 4 | 3d/fshader.glsl 5 | 6 | 7 | -------------------------------------------------------------------------------- /texgen.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/copyicon.png 4 | images/cuticon.png 5 | images/new.png 6 | images/open.png 7 | images/pasteicon.png 8 | images/save.png 9 | images/mainicon.icns 10 | images/mainicon.ico 11 | images/mainicon.png 12 | 13 | 14 | -------------------------------------------------------------------------------- /texgenapplication.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #include "base/textureproject.h" 9 | #include "gui/mainwindow.h" 10 | #include "texgenapplication.h" 11 | #include 12 | 13 | /** 14 | * @brief TexGenApplication::TexGenApplication 15 | * @param argc Number of arguments passed (including the application name). 16 | * @param argv Array of arguments as C char strings. 17 | */ 18 | TexGenApplication::TexGenApplication(int &argc, char* argv[]) : QApplication(argc, argv) 19 | { 20 | addWindow(); 21 | #ifndef Q_OS_MAC 22 | // On Mac OS the platform handles this automatically, 23 | if (argc > 1) { 24 | mainwindows.first()->openFile(QString(argv[1])); 25 | } 26 | #endif 27 | } 28 | 29 | /** 30 | * @brief TexGenApplication::quit 31 | * Tries to close all windows. Stops if one can't be closed. 32 | */ 33 | void TexGenApplication::quit() 34 | { 35 | QMutableVectorIterator it(mainwindows); 36 | it.toBack(); 37 | while (it.hasPrevious()) { 38 | if (it.previous()->close() == false) { 39 | return; 40 | } 41 | } 42 | } 43 | 44 | /** 45 | * @brief TexGenApplication::addWindow 46 | * Adds a new MainWindow. 47 | */ 48 | MainWindow* TexGenApplication::addWindow() 49 | { 50 | auto* newWindow = new MainWindow(this); 51 | QObject::connect(newWindow, &MainWindow::windowTitleChanged, 52 | this, &TexGenApplication::windowUpdated); 53 | QObject::connect(newWindow, &MainWindow::destroyed, 54 | this, &TexGenApplication::removeWindow); 55 | mainwindows.push_back(newWindow); 56 | newWindow->show(); 57 | emit windowsChanged(); 58 | return newWindow; 59 | } 60 | 61 | /** 62 | * @brief TexGenApplication::removeWindow 63 | * @param windowObj The window to be removed. 64 | * Removes a MainWindows from the window list. 65 | */ 66 | void TexGenApplication::removeWindow(QObject* windowObj) 67 | { 68 | int index = mainwindows.indexOf(dynamic_cast(windowObj)); 69 | if (index == -1) { 70 | return; 71 | } 72 | mainwindows.remove(index); 73 | emit windowsChanged(); 74 | } 75 | 76 | /** 77 | * @brief TexGenApplication::windowUpdated 78 | * 79 | * Slot invoked when a program has updated its title. 80 | * Will emit windowsChanged to all the windows, telling them to update their window lists. 81 | */ 82 | void TexGenApplication::windowUpdated(QString) 83 | { 84 | emit windowsChanged(); 85 | } 86 | 87 | /** 88 | * @brief TexGenApplication::event 89 | * Used to handle files being dropped on the application icon in OS X. 90 | */ 91 | bool TexGenApplication::event(QEvent* event) { 92 | if (event->type() == QEvent::FileOpen) { 93 | MainWindow* projectWindow = nullptr; 94 | if (!mainwindows.isEmpty()) { 95 | projectWindow = mainwindows.last(); 96 | } 97 | if (mainwindows.length() != 1 || 98 | (projectWindow && projectWindow->getTextureProject() && 99 | projectWindow->getTextureProject()->isModified())) { 100 | // There are either multiple windows opened or the only one open 101 | // already contains data. Create a new fresh window for this project file. 102 | projectWindow = this->addWindow(); 103 | } 104 | if (projectWindow != nullptr) { 105 | projectWindow->openFile(static_cast(event)->file()); 106 | } 107 | return true; 108 | } 109 | return QApplication::event(event); 110 | } 111 | -------------------------------------------------------------------------------- /texgenapplication.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Part of the ProceduralTextureMaker project. 3 | * http://github.com/johanokl/ProceduralTextureMaker 4 | * Released under GPLv3. 5 | * Johan Lindqvist (johan.lindqvist@gmail.com) 6 | */ 7 | 8 | #ifndef TEXGENAPPLICATION_H 9 | #define TEXGENAPPLICATION_H 10 | 11 | #include 12 | #include 13 | 14 | class QMenu; 15 | class MainWindow; 16 | 17 | /** 18 | * @brief The TexGenApplication class 19 | * Manages the instances of class MainWindow. 20 | * 21 | * All instances of MainWindow has this as their parent object, and all windows' menu 22 | * bars contain links to all the other instances. 23 | * 24 | * Inherits QApplication and adds some convenient application specifc functions. 25 | * Will be destroyed (and the application process exited) when the 26 | * last visible MainWindow is closed. 27 | 28 | */ 29 | class TexGenApplication : public QApplication 30 | { 31 | Q_OBJECT 32 | 33 | public: 34 | TexGenApplication(int &argc, char* argv[]); 35 | virtual ~TexGenApplication() {} 36 | 37 | signals: 38 | void windowsChanged(); 39 | 40 | public slots: 41 | MainWindow* addWindow(); 42 | void removeWindow(QObject*); 43 | void quit(); 44 | void windowUpdated(QString); 45 | 46 | protected: 47 | bool event(QEvent* event); 48 | 49 | public: 50 | QVector mainwindows; 51 | 52 | }; 53 | 54 | 55 | #endif // TEXGENAPPLICATION_H 56 | --------------------------------------------------------------------------------