├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── TODO ├── demo ├── lol.e ├── mandelbrot.e └── uk.e ├── plugins ├── CMakeLists.txt ├── color │ ├── CMakeLists.txt │ ├── ColorNode.cpp │ ├── ColorNode.h │ ├── ColorPlugin.cpp │ ├── ColorPlugin.h │ ├── color.png │ ├── color.qrc │ └── fromToStream.cpp ├── compare │ ├── CMakeLists.txt │ ├── CompNode.cpp │ ├── CompNode.h │ ├── ComparePlugin.cpp │ ├── ComparePlugin.h │ ├── comp.qrc │ ├── eq.png │ ├── gt.png │ ├── lt.png │ └── ne.png ├── condition │ ├── CMakeLists.txt │ ├── ConditionPlugin.cpp │ ├── ConditionPlugin.h │ ├── IfNode.cpp │ ├── IfNode.h │ ├── cond.qrc │ └── if.png ├── functions │ ├── CMakeLists.txt │ ├── Function.cpp │ ├── Function.h │ ├── FunctionManager.cpp │ ├── FunctionManager.h │ ├── FunctionNode.cpp │ ├── FunctionNode.h │ ├── FunctionPlugin.cpp │ ├── FunctionPlugin.h │ ├── arrow.png │ ├── fromToStream.cpp │ ├── func.qrc │ └── functionmanager.ui ├── image │ ├── BitmapNode.cpp │ ├── BitmapNode.h │ ├── CMakeLists.txt │ ├── ImagePlugin.cpp │ ├── ImagePlugin.h │ ├── fromToStream.cpp │ ├── image.png │ └── image.qrc ├── io │ ├── CMakeLists.txt │ ├── ExportImageDialog.cpp │ ├── ExportImageDialog.h │ ├── InputNode.cpp │ ├── InputNode.h │ ├── IoPlugin.cpp │ ├── IoPlugin.h │ ├── OutputNode.cpp │ ├── OutputNode.h │ ├── exportimagedialog.ui │ ├── io.qrc │ ├── output.png │ ├── x.png │ └── y.png ├── logic │ ├── CMakeLists.txt │ ├── LogicNode.cpp │ ├── LogicNode.h │ ├── LogicPlugin.cpp │ ├── LogicPlugin.h │ ├── and.png │ ├── logic.qrc │ ├── not.png │ ├── or.png │ └── xor.png ├── lut │ ├── CMakeLists.txt │ ├── Gradient.cpp │ ├── Gradient.h │ ├── LUTNode.cpp │ ├── LUTNode.h │ ├── LUTPlugin.cpp │ ├── LUTPlugin.h │ ├── dialog │ │ ├── lut_dialog.cpp │ │ └── lut_dialog.h │ └── fromToStream.cpp └── math │ ├── CMakeLists.txt │ ├── ComplexNode.cpp │ ├── ComplexNode.h │ ├── MathNode.cpp │ ├── MathNode.h │ ├── MathPlugin.cpp │ ├── MathPlugin.h │ ├── RealNode.cpp │ ├── RealNode.h │ ├── add.png │ ├── complex.png │ ├── cos.png │ ├── divide.png │ ├── fromToStream.cpp │ ├── math.qrc │ ├── multiply.png │ ├── neg.png │ ├── real.png │ ├── sin.png │ ├── sqrt.png │ └── subtract.png └── src ├── CMakeLists.txt ├── EmergenceInterface.h ├── Node.cpp ├── Node.h ├── NodeBox.cpp ├── NodeBox.h ├── PluginManager.cpp ├── PluginManager.h ├── Workspace.cpp ├── Workspace.h ├── data_t.cpp ├── data_t.h ├── emgc.ico ├── icons ├── copy.png ├── cut.png ├── delete.png ├── exit.png ├── export.png ├── no_icon.png ├── open.png ├── paste.png ├── redo.png ├── save.png └── undo.png ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── signalManager.h └── src.qrc /.gitignore: -------------------------------------------------------------------------------- 1 | Emergence.pro.user 2 | wiki 3 | build 4 | **/*.pro.user 5 | **/CMakeLists.txt.user 6 | CMakeLists.txt.user 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | 3 | project(Emergence) 4 | 5 | if ( NOT CMAKE_BUILD_TYPE ) 6 | set( CMAKE_BUILD_TYPE Release) 7 | endif() 8 | 9 | set(PLUGIN_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/lib) 10 | set(MAIN_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) 11 | set(BIN_SRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) 12 | 13 | add_subdirectory(src) 14 | add_subdirectory(plugins) 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Emergence 2 | Generate bitmaps using nodes. 3 | 4 | ![uk.emrg](https://image.ibb.co/eCYhey/uk2.png) 5 | ![lol.emerg](https://i.imgur.com/dY8D2aa.png) 6 | ![mandelbrot.emrg](https://i.imgur.com/1fQAxWw.png) 7 | 8 | For more information check out the [wiki](https://github.com/bsella/Emergence/wiki). 9 | 10 | --- 11 | 12 | # Building Emergence 13 | For now, Emergence is supported only on the GNU/Linux system. To build it you will need `cmake` and the `Qt5Widgets` library. 14 | 15 | It's highly recommended to build out of the source directory. For example, type the following commands: 16 | 17 | $ mkdir build 18 | $ cd build 19 | $ cmake .. 20 | $ make 21 | 22 | --- 23 | 24 | Check out my TODO-List! 25 | 26 | Feel free to send your feedback to `karim.salama@univ-tlse3.fr` 27 | 28 | --- 29 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - [ ] Navigate/Zoom 2 | - [x] Zoom 3 | - [ ] Navigate 4 | - [x] File oriented 5 | - [x] Clipboard 6 | - [x] Undo/Redo 7 | - [x] Add 8 | - [x] Remove 9 | - [x] Connect 10 | - [x] Disconnect 11 | - [x] Move 12 | - [ ] Change Constant 13 | - [ ] Change Image 14 | - [ ] Change/rename Function 15 | - [x] Multiple outputs 16 | - [x] LUT interface (dialog) 17 | - [ ] Transparancy 18 | - [x] Functions 19 | - [x] Function Manager 20 | - [x] New save format 21 | - [x] Adapt with latest optimisation (pixel ID) 22 | - [x] Draw FunctionNodes 23 | - [ ] Recursive Functions (obsolete if using OpenGL) 24 | - [x] New save format 25 | - [ ] Data structures and lists 26 | - [x] Preventing cycles 27 | - [x] More icons 28 | - [ ] Auto-arrange 29 | - [ ] Options 30 | - [ ] Command line 31 | - [ ] Documentation 32 | - [x] Modularity (Plugin system) 33 | - [ ] Integrate with OpenGL 34 | - [x] Binary and Text save protocol (*.ebin / *.e) 35 | - [ ] Tidy up the architecture 36 | - [ ] A more intuitive way to disconnect node 37 | - [ ] A more intuitive way to change constants 38 | - [ ] Zoom and navigate on render area 39 | - [ ] Time nodes => videos 40 | - [ ] Curvy connections 41 | - [ ] Interpolate colors 42 | - [ ] Themes 43 | -------------------------------------------------------------------------------- /demo/lol.e: -------------------------------------------------------------------------------- 1 | 6 2 | 12 3 | div lut lerp x cos sin neg real out add clamp y 4 | 0 5 | 17 6 | div 283 84 7 | lut 352 77 3 4294901760 0 4278190335 0.5 4278255360 1 8 | lerp 17 75 9 | x -103 -31 10 | cos 87 100 11 | lerp 17 -66 12 | sin 84 -41 13 | neg 80 28 14 | real 19 -129 1 15 | out 510 87 16 | add 224 27 17 | neg -110 40 18 | clamp 163 -66 19 | clamp 164 63 20 | real 224 131 2 21 | y -111 116 22 | real -177 -67 15 23 | 10 14 0 16 15 11 2 16 3 11 5 8 1 12 13 16 8 6 7 8 4 7 24 | -------------------------------------------------------------------------------- /demo/mandelbrot.e: -------------------------------------------------------------------------------- 1 | 6 2 | 9 3 | x real y mul lerp add cplx out neg 4 | 0 5 | 22 6 | x -508 -168 7 | real -497 -116 -2 8 | y -511 -41 9 | real -497 -220 1 10 | mul -176 -198 11 | mul 8 -39 12 | lerp -417 -78 13 | mul -238 -251 14 | add -114 -93 15 | lerp -418 -194 16 | mul 69 14 17 | real -590 -78 1.5 18 | mul -115 -145 19 | mul -54 -92 20 | cplx -357 -107 21 | out 142 66 22 | neg -496 18 23 | add -175 -146 24 | add -237 -199 25 | add -53 -40 26 | add 9 13 27 | add 70 66 28 | 18 18 19 19 11 2 16 14 14 12 14 3 0 1 20 20 17 17 8 8 9 6 21 11 4 14 7 14 13 14 5 14 10 14 29 | -------------------------------------------------------------------------------- /demo/uk.e: -------------------------------------------------------------------------------- 1 | 6 2 | 12 3 | lt real color or gt and add if sub y x out 4 | 0 5 | 89 6 | lt -722 557 7 | real -157 169 0.334 8 | real -157 270 0.666 9 | real -158 321 0.6 10 | real -156 118 0.4 11 | real -156 -86 0.417 12 | real -156 15 0.583 13 | color -23 571 4278199421 14 | real -157 66 0.55 15 | color 135 40 4294967295 16 | real -155 -137 0.45 17 | color -40 380 4294967295 18 | real -450 525 1 19 | real -916 235 1 20 | real -918 394 0.5 21 | lt -63 135 22 | or -92 537 23 | gt -213 461 24 | and 75 -33 25 | and -1 -32 26 | add -450 473 27 | lt -63 186 28 | gt -213 513 29 | and -2 223 30 | if 219 214 31 | and 74 222 32 | or 135 92 33 | color 22 302 4291761195 34 | and -662 374 35 | and -602 -6 36 | gt -722 453 37 | or -544 386 38 | add -916 183 39 | and -603 150 40 | sub -918 291 41 | real -335 453 0.1 42 | y -167 220 43 | and -661 62 44 | and -663 530 45 | and -662 218 46 | real -918 343 0.066 47 | sub -855 210 48 | x -1008 158 49 | out 363 7 50 | out 361 107 51 | out 242 347 52 | out 175 545 53 | and -152 590 54 | and -152 486 55 | gt -213 617 56 | lt -61 1 57 | or 58 93 58 | if 278 84 59 | lt -62 256 60 | if 158 405 61 | if 55 361 62 | gt -213 565 63 | sub -452 581 64 | lt -62 -69 65 | if 278 -18 66 | lt -61 52 67 | if 56 511 68 | lt -62 -120 69 | lt -62 307 70 | and -603 306 71 | gt -721 37 72 | and -604 462 73 | and 56 461 74 | gt -722 89 75 | or -483 248 76 | lt -722 193 77 | lt -722 141 78 | or -543 75 79 | lt -722 245 80 | lt -722 297 81 | gt -723 401 82 | gt -721 -15 83 | gt -723 349 84 | sub -389 500 85 | lt -722 505 86 | real -333 626 -0.1 87 | y -546 578 88 | color -214 402 4294967295 89 | x -542 448 90 | color 136 -11 4291761195 91 | x -167 -35 92 | real -915 131 -0.066 93 | y -1012 288 94 | real -915 79 0 95 | 41 40 4 36 48 47 35 78 62 60 58 50 83 81 1 36 78 80 21 53 82 51 54 15 63 18 25 77 75 76 37 41 88 64 66 42 87 71 39 42 87 65 68 79 0 70 73 32 13 59 52 55 61 56 49 17 22 57 80 85 6 19 23 84 26 24 36 2 27 67 61 27 16 11 35 57 83 81 5 85 84 26 9 85 8 82 16 7 10 85 36 3 74 28 42 14 30 38 69 16 41 86 72 31 87 14 34 88 29 33 86 34 88 34 40 34 88 41 87 14 20 12 42 14 96 | -------------------------------------------------------------------------------- /plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(color) 2 | add_subdirectory(compare) 3 | add_subdirectory(condition) 4 | add_subdirectory(functions) 5 | add_subdirectory(image) 6 | add_subdirectory(logic) 7 | add_subdirectory(lut) 8 | add_subdirectory(math) 9 | add_subdirectory(io) 10 | -------------------------------------------------------------------------------- /plugins/color/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(ColorPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 9 | qt5_add_resources(QRC color.qrc) 10 | add_custom_target(color_qrc DEPENDS ${QRC}) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 13 | 14 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 15 | 16 | add_library(${PROJECT_NAME} SHARED ColorPlugin.cpp ColorPlugin.h) 17 | add_library(color 18 | fromToStream.cpp 19 | ColorNode.cpp 20 | ColorNode.h) 21 | 22 | target_link_libraries(${PROJECT_NAME} color data_t ${QRC}) 23 | add_dependencies(${PROJECT_NAME} color_qrc) 24 | -------------------------------------------------------------------------------- /plugins/color/ColorNode.cpp: -------------------------------------------------------------------------------- 1 | #include "ColorNode.h" 2 | 3 | #include 4 | #include 5 | 6 | ColorNode::ColorNode(const data_t::color& c):Node("color",50,50,c){ 7 | cache=c; 8 | constant=true; 9 | } 10 | 11 | void ColorNode::paint(QPainter *painter, const QStyleOptionGraphicsItem*option, QWidget*widget){ 12 | Node::paint(painter,option,widget); 13 | painter->drawText(boundingRect().center()-QPoint(16,-2),"Color"); 14 | } 15 | void ColorNode::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){ 16 | menu=new QMenu; 17 | connect(menu->addAction(QString("Change color")), &QAction::triggered,this,&ColorNode::changeColor); 18 | Node::contextMenuEvent(event); 19 | } 20 | void ColorNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *){ 21 | changeColor(); 22 | } 23 | 24 | void ColorNode::changeColor(){ 25 | QColor c =QColorDialog::getColor(Qt::white,(QWidget*)parentWidget()); 26 | if(c.isValid()){ 27 | cache=c.rgba(); 28 | color=c; 29 | updateVal(); 30 | emit sm.updateOutputs(); 31 | update(); 32 | } 33 | } 34 | 35 | RGBNode::RGBNode():Node("rgb",50,100,Qt::white,3){} 36 | HSVNode::HSVNode():Node("hsv",50,100,Qt::white,3){} 37 | 38 | void RGBNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 39 | Node::paint(painter, option, widget); 40 | painter->fillRect(QRect(socketSize+2,height/4-5,width-4,10),Qt::red); 41 | painter->fillRect(QRect(socketSize+2,2*height/4-5,width-4,10),Qt::green); 42 | painter->fillRect(QRect(socketSize+2,3*height/4-5,width-4,10),Qt::blue); 43 | } 44 | 45 | void HSVNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 46 | Node::paint(painter, option, widget); 47 | painter->drawText(width/4,height/4+4,"H"); 48 | painter->drawText(width/4,2*height/4+4,"S"); 49 | painter->drawText(width/4,3*height/4+4,"V"); 50 | } 51 | 52 | data_t RGBNode::kernel()const{ 53 | int r=double(iNodes[0]->eval())*255, 54 | g=double(iNodes[1]->eval())*255, 55 | b=double(iNodes[2]->eval())*255; 56 | r=qMax(r,0); r= qMin(r,255); 57 | g=qMax(g,0); g= qMin(g,255); 58 | b=qMax(b,0); b= qMin(b,255); 59 | return qRgb(r,g,b); 60 | } 61 | 62 | data_t HSVNode::kernel()const{ 63 | int h=double(iNodes[0]->eval())*360, 64 | s=double(iNodes[1]->eval())*255, 65 | v=double(iNodes[2]->eval())*255; 66 | h=qMax(h,0); h= qMin(h,359); 67 | s=qMax(s,0); s= qMin(s,255); 68 | v=qMax(v,0); v= qMin(v,255); 69 | return QColor::fromHsv(h,s,v).rgb(); 70 | } 71 | -------------------------------------------------------------------------------- /plugins/color/ColorNode.h: -------------------------------------------------------------------------------- 1 | #ifndef COLORNODE_H 2 | #define COLORNODE_H 3 | 4 | #include "Node.h" 5 | #include "data_t.h" 6 | 7 | class ColorNode : public Node{ 8 | public: 9 | ColorNode(const data_t::color& c= 0xff000000); 10 | static Node* makeFromBin(std::istream&); 11 | static Node* makeFromText(std::istream&); 12 | private: 13 | inline data_t kernel()const{return cache;} 14 | void paint(QPainter*, 15 | const QStyleOptionGraphicsItem*, 16 | QWidget*); 17 | void contextMenuEvent(QGraphicsSceneContextMenuEvent*); 18 | void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*)override; 19 | void changeColor(); 20 | void toBin(std::ostream&)const override; 21 | void toText(std::ostream&)const override; 22 | }; 23 | 24 | class RGBNode : public Node{ 25 | public: 26 | RGBNode(); 27 | inline static Node* makeNode(std::istream&){return new RGBNode;} 28 | private: 29 | data_t kernel()const; 30 | void paint(QPainter* painter, 31 | const QStyleOptionGraphicsItem*option, 32 | QWidget *widget); 33 | }; 34 | 35 | class HSVNode : public Node{ 36 | public: 37 | HSVNode(); 38 | inline static Node* makeNode(std::istream&){return new HSVNode;} 39 | private: 40 | data_t kernel()const; 41 | void paint(QPainter* painter, 42 | const QStyleOptionGraphicsItem*option, 43 | QWidget *widget); 44 | }; 45 | #endif // COLORNODE_H 46 | -------------------------------------------------------------------------------- /plugins/color/ColorPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "ColorPlugin.h" 2 | #include "ColorNode.h" 3 | 4 | void ColorPlugin::updateUI(Ui::MainWindow *ui) const{ 5 | QMenu* colorMenu = new QMenu("Color",ui->menuInsert); 6 | ui->menuInsert->addAction(colorMenu->menuAction()); 7 | QAction* colorAction= new QAction(QIcon(":/color.png"),"Color"); 8 | QAction* rgbAction= new QAction("RGB"); 9 | QAction* hsvAction= new QAction("HSV"); 10 | 11 | Workspace* ws= (Workspace*)ui->workspace->scene(); 12 | connect(colorAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("color"));}); 13 | connect(rgbAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("rgb"));}); 14 | connect(hsvAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("hsv"));}); 15 | 16 | colorMenu->addAction(colorAction); 17 | colorMenu->addAction(rgbAction); 18 | colorMenu->addAction(hsvAction); 19 | 20 | } 21 | 22 | void ColorPlugin::init()const{ 23 | Node::makeNodeBinTextMethods["color"] = {&ColorNode::makeFromBin, &ColorNode::makeFromText}; 24 | Node::makeNodeBinTextMethods["rgb"] = {&RGBNode::makeNode, &RGBNode::makeNode}; 25 | Node::makeNodeBinTextMethods["hsv"] = {&HSVNode::makeNode, &HSVNode::makeNode}; 26 | 27 | NodeBox::addTool("color","Color",QIcon(":/color.png"),"Color"); 28 | NodeBox::addTool("rgb","RGB","Color"); 29 | NodeBox::addTool("hsv","HSV","Color"); 30 | } 31 | -------------------------------------------------------------------------------- /plugins/color/ColorPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef COLORPLUGIN_H 2 | #define COLORPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class ColorPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const override; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/color/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/color/color.png -------------------------------------------------------------------------------- /plugins/color/color.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | color.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /plugins/color/fromToStream.cpp: -------------------------------------------------------------------------------- 1 | #include "ColorNode.h" 2 | #include 3 | 4 | static Node* askForColor(){ 5 | QColor c= QColorDialog::getColor(Qt::white); 6 | if(c.isValid()) 7 | return new ColorNode(c.rgba()); 8 | return nullptr; 9 | } 10 | 11 | Node* ColorNode::makeFromBin(std::istream& in){ 12 | if(in.peek()!=EOF){ 13 | data_t::color clr; 14 | in.read(reinterpret_cast(&clr),sizeof(data_t::color)); 15 | return new ColorNode(clr); 16 | } 17 | return askForColor(); 18 | } 19 | 20 | Node* ColorNode::makeFromText(std::istream& in){ 21 | if(in.peek()!=EOF){ 22 | data_t::color clr; 23 | in>>clr; 24 | return new ColorNode(clr); 25 | } 26 | return askForColor(); 27 | } 28 | 29 | void ColorNode::toBin(std::ostream &out) const{ 30 | Node::toBin(out); 31 | out.write(reinterpret_cast(&cache.clr),sizeof(data_t::color)); 32 | } 33 | 34 | void ColorNode::toText(std::ostream &out) const{ 35 | Node::toText(out); 36 | out <<' '<eval() > iNodes[1]->eval(); 29 | } 30 | data_t LTNode::kernel()const{ 31 | return iNodes[0]->eval() < iNodes[1]->eval(); 32 | } 33 | data_t EQNode::kernel()const{ 34 | return iNodes[0]->eval() == iNodes[1]->eval(); 35 | } 36 | data_t NENode::kernel()const{ 37 | return iNodes[0]->eval() != iNodes[1]->eval(); 38 | } 39 | -------------------------------------------------------------------------------- /plugins/compare/CompNode.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPNODE_H 2 | #define COMPNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class CompNode:public Node{ 7 | protected: 8 | CompNode(const std::string &type); 9 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem*option, QWidget*widget)=0; 10 | }; 11 | 12 | class GTNode:public CompNode{ 13 | data_t kernel()const; 14 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 15 | public: 16 | GTNode(); 17 | inline static Node* makeNode(std::istream&){return new GTNode;} 18 | }; 19 | 20 | class LTNode:public CompNode{ 21 | data_t kernel()const; 22 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 23 | public: 24 | LTNode(); 25 | inline static Node* makeNode(std::istream&){return new LTNode;} 26 | }; 27 | 28 | class EQNode:public CompNode{ 29 | data_t kernel()const; 30 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 31 | public: 32 | EQNode(); 33 | inline static Node* makeNode(std::istream&){return new EQNode;} 34 | }; 35 | 36 | class NENode:public CompNode{ 37 | data_t kernel()const; 38 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 39 | public: 40 | NENode(); 41 | inline static Node* makeNode(std::istream&){return new NENode;} 42 | }; 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /plugins/compare/ComparePlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "ComparePlugin.h" 2 | #include "CompNode.h" 3 | 4 | void ComparePlugin::updateUI(Ui::MainWindow*ui) const{ 5 | QMenu* compMenu = new QMenu("Compare",ui->menuInsert); 6 | ui->menuInsert->addAction(compMenu->menuAction()); 7 | QAction* gtAction= new QAction(QIcon(":/gt.png"), "Greater Than"); 8 | QAction* ltAction= new QAction(QIcon(":/lt.png"), "Less Than"); 9 | QAction* eqAction= new QAction(QIcon(":/eq.png"), "Equal"); 10 | QAction* neAction= new QAction(QIcon(":/ne.png"), "Not Equal"); 11 | 12 | Workspace* ws= (Workspace*)ui->workspace->scene(); 13 | connect(gtAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("gt"));}); 14 | connect(ltAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("lt"));}); 15 | connect(eqAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("eq"));}); 16 | connect(neAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("ne"));}); 17 | 18 | compMenu->addAction(gtAction); 19 | compMenu->addAction(ltAction); 20 | compMenu->addAction(eqAction); 21 | compMenu->addAction(neAction); 22 | 23 | } 24 | 25 | void ComparePlugin::init()const{ 26 | Node::makeNodeBinTextMethods["gt"] = {>Node::makeNode,>Node::makeNode}; 27 | Node::makeNodeBinTextMethods["lt"] = {<Node::makeNode,<Node::makeNode}; 28 | Node::makeNodeBinTextMethods["eq"] = {&EQNode::makeNode,&EQNode::makeNode}; 29 | Node::makeNodeBinTextMethods["ne"] = {&NENode::makeNode,&NENode::makeNode}; 30 | 31 | NodeBox::addTool("gt","Greater Than",QIcon(":/gt.png"),"Compare"); 32 | NodeBox::addTool("lt","Less Than",QIcon(":/lt.png"),"Compare"); 33 | NodeBox::addTool("eq","Equal",QIcon(":/eq.png"),"Compare"); 34 | NodeBox::addTool("ne","Not Equal",QIcon(":/ne.png"),"Compare"); 35 | } 36 | -------------------------------------------------------------------------------- /plugins/compare/ComparePlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPAREPLUGIN_H 2 | #define COMPAREPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class ComparePlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/compare/comp.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | eq.png 4 | gt.png 5 | lt.png 6 | ne.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /plugins/compare/eq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/compare/eq.png -------------------------------------------------------------------------------- /plugins/compare/gt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/compare/gt.png -------------------------------------------------------------------------------- /plugins/compare/lt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/compare/lt.png -------------------------------------------------------------------------------- /plugins/compare/ne.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/compare/ne.png -------------------------------------------------------------------------------- /plugins/condition/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(ConditionPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 9 | qt5_add_resources(QRC cond.qrc) 10 | add_custom_target(cond_qrc DEPENDS ${QRC}) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 13 | 14 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 15 | 16 | add_library(${PROJECT_NAME} SHARED ConditionPlugin.cpp ConditionPlugin.h) 17 | add_library(cond 18 | IfNode.cpp 19 | IfNode.h) 20 | 21 | target_link_libraries(${PROJECT_NAME} cond data_t ${QRC}) 22 | add_dependencies(${PROJECT_NAME} cond_qrc) 23 | -------------------------------------------------------------------------------- /plugins/condition/ConditionPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "ConditionPlugin.h" 2 | #include "IfNode.h" 3 | 4 | void ConditionPlugin::updateUI(Ui::MainWindow*ui) const{ 5 | QAction* ifAction= new QAction(QIcon(":/if.png"),"Condition"); 6 | 7 | Workspace* ws=(Workspace*)ui->workspace->scene(); 8 | connect(ifAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("if"));}); 9 | 10 | ui->menuInsert->addAction(ifAction); 11 | } 12 | 13 | void ConditionPlugin::init()const{ 14 | Node::makeNodeBinTextMethods["if"] = {&IfNode::makeNode,&IfNode::makeNode}; 15 | 16 | NodeBox::addTool("if","Condition",QIcon(":/if.png")); 17 | } 18 | -------------------------------------------------------------------------------- /plugins/condition/ConditionPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef CONDITIONPLUGIN_H 2 | #define CONDITIONPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class ConditionPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/condition/IfNode.cpp: -------------------------------------------------------------------------------- 1 | #include "IfNode.h" 2 | 3 | #include 4 | 5 | IfNode::IfNode():Node("if",50,100,QColor(180,180,255),3){} 6 | 7 | void IfNode::paint(QPainter* painter, 8 | const QStyleOptionGraphicsItem*option, 9 | QWidget*widget){ 10 | Node::paint(painter,option,widget); 11 | painter->setPen(QPen(Qt::black,1)); 12 | QRectF rect=boundingRect(); 13 | painter->drawText(rect.topLeft()+QPointF(8,rect.height()/4.0+4),"THEN"); 14 | painter->drawText(rect.topLeft()+QPointF(8,2*rect.height()/4.0+4),"IF"); 15 | painter->drawText(rect.topLeft()+QPointF(8,3*rect.height()/4.0+4),"ELSE"); 16 | } 17 | 18 | data_t IfNode::kernel()const{ 19 | return iNodes[1]->eval()? iNodes[0]->eval() : iNodes[2]->eval(); 20 | } 21 | -------------------------------------------------------------------------------- /plugins/condition/IfNode.h: -------------------------------------------------------------------------------- 1 | #ifndef IFNODE_H 2 | #define IFNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class IfNode:public Node{ 7 | public: 8 | IfNode(); 9 | inline static Node* makeNode(std::istream&){return new IfNode;} 10 | private: 11 | data_t kernel()const; 12 | void paint(QPainter* painter, 13 | const QStyleOptionGraphicsItem* option, 14 | QWidget*widget); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /plugins/condition/cond.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | if.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /plugins/condition/if.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/condition/if.png -------------------------------------------------------------------------------- /plugins/functions/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(FunctionsPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTOUIC ON) 8 | set(CMAKE_AUTORCC ON) 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 10 | qt5_add_resources(QRC func.qrc) 11 | add_custom_target(func_qrc DEPENDS ${QRC}) 12 | 13 | qt5_wrap_ui(UI_HEADERS functionmanager.ui) 14 | 15 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 16 | 17 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 18 | 19 | add_library(${PROJECT_NAME} SHARED FunctionPlugin.cpp FunctionPlugin.h) 20 | add_library(func 21 | FunctionNode.cpp 22 | Function.cpp 23 | FunctionManager.cpp 24 | FunctionNode.h 25 | Function.h 26 | FunctionManager.h 27 | fromToStream.cpp 28 | ${UI_HEADERS}) 29 | 30 | target_link_libraries(${PROJECT_NAME} func data_t ${QRC}) 31 | add_dependencies(${PROJECT_NAME} func_qrc) 32 | -------------------------------------------------------------------------------- /plugins/functions/Function.cpp: -------------------------------------------------------------------------------- 1 | #include "Function.h" 2 | #include "FunctionNode.h" 3 | 4 | #include 5 | 6 | Function::FunctionInputNode::FunctionInputNode(int rank):Node("fin",40,40,Qt::lightGray),_rank(rank){ 7 | actionDelete->setEnabled(false); 8 | } 9 | void Function::FunctionInputNode::paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w){ 10 | Node::paint(p,o,w); 11 | QRectF rect= boundingRect(); 12 | p->drawText(rect.topLeft()+QPointF(8,2*rect.height()/4.0+4),QString::number(_rank)); 13 | } 14 | data_t Function::FunctionInputNode::kernel()const{ 15 | return FunctionNode::current->iNodes[_rank]->eval(); 16 | } 17 | 18 | Function::FunctionOutputNode::FunctionOutputNode():Node("fout",50,50,Qt::lightGray,1,true){ 19 | actionDelete->setEnabled(false); 20 | } 21 | void Function::FunctionOutputNode::paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w){ 22 | Node::paint(p,o,w); 23 | Node::drawIcon(p,":/arrow.png"); 24 | } 25 | 26 | Function::Function(int n, const QString& name):QListWidgetItem(name), nbArgs(n){ 27 | scene= new Workspace; 28 | start= new FunctionOutputNode; 29 | scene->addItem(start); 30 | for(int i=0;iaddItem(iNodes[i]); 33 | } 34 | } 35 | Function::Function(){ 36 | scene= new Workspace; 37 | } 38 | Function::~Function(){ 39 | for(int i=nbArgs-1;i>=0;i--) 40 | delete iNodes[i]; 41 | delete start; 42 | // delete scene; 43 | } 44 | 45 | Function::FunctionOutputNode * Function::getOutputFromScene()const{ 46 | for(const auto& n: scene->nodes()) 47 | if(n->_type=="fout") 48 | return (FunctionOutputNode*)n; 49 | return nullptr; 50 | } 51 | Function::FunctionInputNode *Function::getNthInputFromScene(int n)const{ 52 | for(const auto& node: scene->nodes()) 53 | if(node->_type=="fin"&& ((FunctionInputNode*)node)->_rank==n) 54 | return (FunctionInputNode*)node; 55 | return nullptr; 56 | } 57 | -------------------------------------------------------------------------------- /plugins/functions/Function.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTION_H 2 | #define FUNCTION_H 3 | 4 | #include "Node.h" 5 | #include 6 | #include "Workspace.h" 7 | 8 | class Function: public QListWidgetItem{ 9 | public: 10 | struct FunctionInputNode: public Node{ 11 | FunctionInputNode(int rank); 12 | const int _rank; 13 | data_t kernel()const; 14 | void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); 15 | void toBin(std::ostream &)const; 16 | void toText(std::ostream &)const; 17 | static Node* makefromBin(std::istream&); 18 | static Node* makefromText(std::istream&); 19 | }; 20 | struct FunctionOutputNode: Node{ 21 | FunctionOutputNode(); 22 | inline data_t kernel()const{return iNodes[0]->eval();} 23 | inline static Node* makeNode(std::istream&){return new FunctionOutputNode;} 24 | void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); 25 | }; 26 | Function(int,const QString&); 27 | Function(); 28 | ~Function(); 29 | int nbArgs; 30 | FunctionOutputNode* start; 31 | QVector iNodes; 32 | Workspace* scene; 33 | void toBin(std::ostream& out)const; 34 | void toText(std::ostream& out)const; 35 | FunctionOutputNode* getOutputFromScene()const; 36 | FunctionInputNode* getNthInputFromScene(int n)const; 37 | }; 38 | 39 | 40 | #endif // FUNCTION_H 41 | -------------------------------------------------------------------------------- /plugins/functions/FunctionManager.cpp: -------------------------------------------------------------------------------- 1 | #include "FunctionManager.h" 2 | #include "ui_functionmanager.h" 3 | 4 | FunctionManager* FunctionManager::singleton=0; 5 | FunctionManager* FunctionManager::instance(){ 6 | if(singleton==0) 7 | singleton= new FunctionManager; 8 | return singleton; 9 | } 10 | FunctionManager::FunctionManager(QWidget *parent): 11 | QDialog(parent), ui(new Ui::FunctionManager){ 12 | ui->setupUi(this); 13 | ui->workspace->setAcceptDrops(true); 14 | ui->workspace->setDragMode(QGraphicsView::DragMode::RubberBandDrag); 15 | ui->removeFunctionButton->setEnabled(false); 16 | connect(ui->listWidget,SIGNAL(itemDoubleClicked(QListWidgetItem*)),this,SLOT(renameFunction(QListWidgetItem*))); 17 | connect(ui->listWidget,&QListWidget::currentItemChanged,this,&FunctionManager::setFunction); 18 | connect(ui->buttonBox,SIGNAL(accepted()),this,SLOT(accept())); 19 | connect(ui->buttonBox,SIGNAL(rejected()),this,SLOT(reject())); 20 | 21 | del.setShortcut(QKeySequence::Delete); 22 | copy.setShortcut(QKeySequence::Copy); 23 | cut.setShortcut(QKeySequence::Cut); 24 | paste.setShortcut(QKeySequence::Paste); 25 | select_all.setShortcut(QKeySequence::SelectAll); 26 | undo.setShortcut(QKeySequence::Undo); 27 | redo.setShortcut(QKeySequence::Redo); 28 | addAction(&undo); 29 | addAction(&redo); 30 | addAction(&select_all); 31 | addAction(&paste); 32 | addAction(&cut); 33 | addAction(©); 34 | addAction(&del); 35 | } 36 | 37 | void FunctionManager::accept(){ 38 | undoStack.setClean(); 39 | for(int i=0; ilistWidget->count();i++) 40 | ((Function*)ui->listWidget->item(i))->scene->undoStack.setClean(); 41 | QDialog::accept(); 42 | } 43 | void FunctionManager::reject(){ 44 | while(!undoStack.isClean()) 45 | undoStack.undo(); 46 | for(int i=0; ilistWidget->count();i++){ 47 | Function *f=(Function*)ui->listWidget->item(i); 48 | while(!f->scene->undoStack.isClean()) 49 | f->scene->undoStack.undo(); 50 | } 51 | QDialog::reject(); 52 | } 53 | 54 | FunctionManager::~FunctionManager(){ 55 | delete ui; 56 | } 57 | 58 | Function* FunctionManager::functionAt(int i){ 59 | return (Function*)instance()->ui->listWidget->item(i); 60 | } 61 | int FunctionManager::indexOf(Function *f){ 62 | return instance()->ui->listWidget->row(f); 63 | } 64 | int FunctionManager::count(){ 65 | return instance()->ui->listWidget->count(); 66 | } 67 | 68 | void FunctionManager::on_addFunctionButton_clicked(){ 69 | undoStack.push(new AddFunctionCommand); 70 | } 71 | void FunctionManager::on_removeFunctionButton_clicked(){ 72 | undoStack.push(new RemoveFunctionCommand); 73 | } 74 | void FunctionManager::renameFunction(QListWidgetItem *item){ 75 | QString newname= QInputDialog::getText(this,"Change function name", "Name :"); 76 | if(!newname.isNull()){ 77 | newname.replace(' ','_'); 78 | undoStack.push(new RenameFunctionCommand((Function*)item,newname)); 79 | } 80 | } 81 | 82 | Function* FunctionManager::getFunction(FunctionNode *node){ 83 | if(node) instance()->ui->listWidget->setCurrentItem(node->func); 84 | if(instance()->exec()) 85 | return (Function*)instance()->ui->listWidget->currentItem(); 86 | return nullptr; 87 | } 88 | 89 | bool FunctionManager::userIntented=true; 90 | 91 | void FunctionManager::on_spinBox_valueChanged(int arg1){ 92 | if(userIntented){ 93 | Function* func=(Function*)ui->listWidget->currentItem(); 94 | func->scene->undoStack.push(new ChangeNbArgsCommand(func,func->nbArgs,arg1)); 95 | } 96 | } 97 | 98 | void FunctionManager::setFunction(QListWidgetItem* curr, QListWidgetItem* prev){ 99 | if(!curr){ 100 | ui->workspace->setScene(0); 101 | ui->spinBox->setEnabled(false); 102 | ui->removeFunctionButton->setEnabled(false); 103 | return; 104 | } 105 | ui->spinBox->setEnabled(true); 106 | ui->removeFunctionButton->setEnabled(true); 107 | if(Function* fPrev=(Function*)prev){ 108 | disconnect(&redo,SIGNAL(triggered(bool)),&fPrev->scene->undoStack,SLOT(redo())); 109 | disconnect(&undo,SIGNAL(triggered(bool)),&fPrev->scene->undoStack,SLOT(undo())); 110 | disconnect(&select_all,SIGNAL(triggered(bool)),fPrev->scene,SLOT(select_all())); 111 | disconnect(&paste,SIGNAL(triggered(bool)),fPrev->scene,SLOT(paste())); 112 | disconnect(&cut,SIGNAL(triggered(bool)),fPrev->scene,SLOT(cut())); 113 | disconnect(©,SIGNAL(triggered(bool)),fPrev->scene,SLOT(copy())); 114 | disconnect(&del,SIGNAL(triggered(bool)),fPrev->scene,SLOT(delete_selected())); 115 | } 116 | if(Function* fCurr=(Function*)curr){ 117 | ui->workspace->setScene(fCurr->scene); 118 | userIntented=false; 119 | ui->spinBox->setValue(fCurr->nbArgs); 120 | userIntented=true; 121 | connect(&del,SIGNAL(triggered(bool)),fCurr->scene,SLOT(delete_selected())); 122 | connect(©,SIGNAL(triggered(bool)),fCurr->scene,SLOT(copy())); 123 | connect(&cut,SIGNAL(triggered(bool)),fCurr->scene,SLOT(cut())); 124 | connect(&paste,SIGNAL(triggered(bool)),fCurr->scene,SLOT(paste())); 125 | connect(&select_all,SIGNAL(triggered(bool)),fCurr->scene,SLOT(select_all())); 126 | connect(&undo,SIGNAL(triggered(bool)),&fCurr->scene->undoStack,SLOT(undo())); 127 | connect(&redo,SIGNAL(triggered(bool)),&fCurr->scene->undoStack,SLOT(redo())); 128 | } 129 | } 130 | 131 | ChangeNbArgsCommand::ChangeNbArgsCommand(Function* f,int from, int to,QUndoCommand* parent) 132 | :QUndoCommand(parent){ 133 | _from=from; 134 | _to=to; 135 | func=f; 136 | } 137 | void ChangeNbArgsCommand::undo(){ 138 | if(_to>_from) 139 | for(int i=_from; i<_to; i++){ 140 | func->scene->removeItem(func->iNodes[i]); 141 | delete func->iNodes[i]; 142 | func->iNodes.pop_back(); 143 | } 144 | else 145 | for(int i=_to; i<_from; i++){ 146 | func->iNodes.push_back(new Function::FunctionInputNode(i)); 147 | func->scene->addItem(func->iNodes[i]); 148 | } 149 | func->nbArgs=_from; 150 | FunctionManager::userIntented=false; 151 | FunctionManager::instance()->ui->spinBox->setValue(_from); 152 | FunctionManager::userIntented=true; 153 | func->scene->update(); 154 | } 155 | void ChangeNbArgsCommand::redo(){ 156 | if(_to>_from) 157 | for(int i=_from; i<_to; i++){ 158 | func->iNodes.push_back(new Function::FunctionInputNode(i)); 159 | func->scene->addItem(func->iNodes[i]); 160 | } 161 | else 162 | for(int i=_to; i<_from; i++){ 163 | func->scene->removeItem(func->iNodes[i]); 164 | delete func->iNodes[i]; 165 | func->iNodes.pop_back(); 166 | } 167 | func->nbArgs=_to; 168 | FunctionManager::userIntented=false; 169 | FunctionManager::instance()->ui->spinBox->setValue(_to); 170 | FunctionManager::userIntented=true; 171 | func->scene->update(); 172 | } 173 | 174 | AddFunctionCommand::AddFunctionCommand(QUndoCommand*parent) 175 | :QUndoCommand(parent){ 176 | func= new Function(0,"New_Function"); 177 | } 178 | void AddFunctionCommand::undo(){ 179 | QObject::disconnect(func->start,SIGNAL(disconnected(Node::Socket*)),func->scene,SLOT(disconnectNode(Node::Socket*))); 180 | QObject::disconnect(func->start,SIGNAL(connected(Node::Socket*,Node*)),func->scene,SLOT(connectNode(Node::Socket*,Node*))); 181 | for(Node* n:func->iNodes){ 182 | QObject::disconnect(n,SIGNAL(connected(Node::Socket*,Node*)),func->scene,SLOT(connectNode(Node::Socket*,Node*))); 183 | QObject::disconnect(n,SIGNAL(disconnected(Node::Socket*)),func->scene,SLOT(disconnectNode(Node::Socket*))); 184 | } 185 | delete func; 186 | FunctionManager::instance()->ui->removeFunctionButton->setEnabled( 187 | FunctionManager::instance()->ui->listWidget->count()>1); 188 | } 189 | void AddFunctionCommand::redo(){ 190 | FunctionManager::instance()->ui->listWidget->addItem(func); 191 | 192 | QObject::connect(func->start,SIGNAL(connected(Node::Socket*,Node*)),func->scene,SLOT(connectNode(Node::Socket*,Node*))); 193 | QObject::connect(func->start,SIGNAL(disconnected(Node::Socket*)),func->scene,SLOT(disconnectNode(Node::Socket*))); 194 | for(Node* n:func->iNodes){ 195 | QObject::connect(n,SIGNAL(connected(Node::Socket*,Node*)),func->scene,SLOT(connectNode(Node::Socket*,Node*))); 196 | QObject::connect(n,SIGNAL(disconnected(Node::Socket*)),func->scene,SLOT(disconnectNode(Node::Socket*))); 197 | } 198 | FunctionManager::instance()->ui->removeFunctionButton->setEnabled(true); 199 | } 200 | 201 | RemoveFunctionCommand::RemoveFunctionCommand(QUndoCommand *parent) 202 | :QUndoCommand(parent){ 203 | _rank=FunctionManager::instance()->ui->listWidget->currentRow(); 204 | } 205 | void RemoveFunctionCommand::undo(){ 206 | FunctionManager::instance()->ui->listWidget->insertItem(_rank,func); 207 | FunctionManager::instance()->ui->removeFunctionButton->setEnabled(true); 208 | } 209 | void RemoveFunctionCommand::redo(){ 210 | func=(Function*)FunctionManager::instance()->ui->listWidget->takeItem(_rank); 211 | FunctionManager::instance()->ui->removeFunctionButton->setEnabled( 212 | FunctionManager::instance()->ui->listWidget->count()); 213 | } 214 | 215 | RenameFunctionCommand::RenameFunctionCommand(Function *f, const QString &to, QUndoCommand *parent) 216 | :QUndoCommand(parent){ 217 | func=f; 218 | _from=f->text(); 219 | _to=to; 220 | } 221 | void RenameFunctionCommand::undo(){ 222 | func->setText(_from); 223 | } 224 | void RenameFunctionCommand::redo(){ 225 | func->setText(_to); 226 | } 227 | 228 | void FunctionManager::clear(){ 229 | instance()->ui->workspace->setScene(0); 230 | while(instance()->ui->listWidget->count()) 231 | delete instance()->ui->listWidget->takeItem(0); 232 | instance()->ui->removeFunctionButton->setEnabled(false); 233 | instance()->ui->spinBox->setEnabled(false); 234 | } 235 | void FunctionManager::fromBin(std::istream& in)const{ 236 | Function *f= new Function; 237 | std::string str; 238 | in >> str; 239 | in.ignore(1); 240 | f->setText(QString::fromStdString(str)); 241 | f->scene->fromBin(in); 242 | 243 | f->start= f->getOutputFromScene(); 244 | in.read(reinterpret_cast(&f->nbArgs),sizeof(int)); 245 | for(int i=0; inbArgs;i++) 246 | f->iNodes.push_back(f->getNthInputFromScene(i)); 247 | ui->listWidget->addItem(f); 248 | } 249 | void FunctionManager::fromText(std::istream& in)const{ 250 | Function *f= new Function; 251 | std::string str; 252 | in >> str; 253 | f->setText(QString::fromStdString(str)); 254 | f->scene->fromText(in); 255 | 256 | f->start= f->getOutputFromScene(); 257 | in >> f->nbArgs; 258 | for(int i=0; inbArgs;i++) 259 | f->iNodes.push_back(f->getNthInputFromScene(i)); 260 | ui->listWidget->addItem(f); 261 | } 262 | -------------------------------------------------------------------------------- /plugins/functions/FunctionManager.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTIONMANAGER_H 2 | #define FUNCTIONMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Function.h" 10 | #include "FunctionNode.h" 11 | 12 | namespace Ui { 13 | class FunctionManager; 14 | } 15 | 16 | class FunctionManager : public QDialog{ 17 | Q_OBJECT 18 | public: 19 | static FunctionManager* instance(); 20 | static Function* getFunction(FunctionNode* node=0); 21 | static Function* functionAt(int); 22 | static int indexOf(Function*); 23 | static int count(); 24 | static void clear(); 25 | void fromBin(std::istream&)const; 26 | void fromText(std::istream&)const; 27 | private: 28 | explicit FunctionManager(QWidget *parent = 0); 29 | ~FunctionManager(); 30 | static FunctionManager* singleton; 31 | static bool userIntented; 32 | Ui::FunctionManager *ui; 33 | QAction del,copy,cut,paste,undo,redo,select_all; 34 | QUndoStack undoStack; 35 | void setFunction(QListWidgetItem *,QListWidgetItem*); 36 | friend class ChangeNbArgsCommand; 37 | friend class AddFunctionCommand; 38 | friend class RemoveFunctionCommand; 39 | friend class RenameFunctionCommand; 40 | private slots: 41 | void accept(); 42 | void reject(); 43 | void renameFunction(QListWidgetItem*); 44 | void on_spinBox_valueChanged(int arg1); 45 | void on_addFunctionButton_clicked(); 46 | void on_removeFunctionButton_clicked(); 47 | }; 48 | 49 | class ChangeNbArgsCommand:public QUndoCommand{ 50 | public: 51 | ChangeNbArgsCommand(Function*, int, int, QUndoCommand* parent=0); 52 | private: 53 | int _from; 54 | int _to; 55 | Function* func; 56 | void undo(); 57 | void redo(); 58 | }; 59 | 60 | class AddFunctionCommand:public QUndoCommand{ 61 | public: 62 | explicit AddFunctionCommand(QUndoCommand*parent=0); 63 | private: 64 | Function* func; 65 | void undo(); 66 | void redo(); 67 | }; 68 | class RemoveFunctionCommand:public QUndoCommand{ 69 | public: 70 | explicit RemoveFunctionCommand(QUndoCommand*parent=0); 71 | private: 72 | uint _rank; 73 | Function* func; 74 | void undo(); 75 | void redo(); 76 | }; 77 | class RenameFunctionCommand:public QUndoCommand{ 78 | public: 79 | RenameFunctionCommand(Function*,const QString& to, 80 | QUndoCommand* parent=0); 81 | private: 82 | Function* func; 83 | QString _from; 84 | QString _to; 85 | void undo(); 86 | void redo(); 87 | }; 88 | 89 | #endif // FUNCTIONMANAGER_H 90 | -------------------------------------------------------------------------------- /plugins/functions/FunctionNode.cpp: -------------------------------------------------------------------------------- 1 | #include "FunctionNode.h" 2 | 3 | #include 4 | #include "FunctionManager.h" 5 | 6 | uint FunctionNode::nbNodes=0; 7 | FunctionNode::FunctionNode(Function* f) 8 | :Node("fun",60,50+10*f->nbArgs,Qt::lightGray,f->nbArgs), 9 | func(f),nodeNumber(nbNodes++){} 10 | FunctionNode::FunctionNode():Node("fun",60,50,Qt::lightGray),nodeNumber(nbNodes++){} 11 | FunctionNode::~FunctionNode(){ 12 | nbNodes--; 13 | } 14 | 15 | void FunctionNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *){ 16 | Function* newFunc=FunctionManager::getFunction(); 17 | if(newFunc){ 18 | func=newFunc; 19 | changeNbArgs(func->nbArgs); 20 | } 21 | update(); 22 | } 23 | 24 | void FunctionNode::paint(QPainter *p, const QStyleOptionGraphicsItem *o, QWidget *w){ 25 | Node::paint(p,o,w); 26 | QRectF rect = boundingRect(); 27 | if(func) 28 | p->drawText(rect.topLeft()+QPointF(8,rect.height()/2.0+4),func->text()); 29 | } 30 | 31 | void FunctionNode::changeNbArgs(uint args){ 32 | if(nbArgs==args) return; 33 | height=50+10*args; 34 | if(args>nbArgs) 35 | for(uint i=nbArgs; idisconnectNode(); 42 | delete sockets.back(); 43 | sockets.pop_back(); 44 | iNodes.pop_back(); 45 | } 46 | nbArgs=args; 47 | update(); 48 | } 49 | 50 | FunctionNode::operator bool()const{ 51 | if(func) 52 | return Node::operator bool()&& *func->start; 53 | return false; 54 | } 55 | 56 | FunctionNode* FunctionNode::current; 57 | 58 | data_t FunctionNode::eval(){ 59 | if(constant) return cache; 60 | if(pixelID==lastPixelID) return cache; 61 | 62 | current=this; 63 | pixelID+=nodeNumber+1; 64 | 65 | cache=kernel(); 66 | 67 | /// I have no idea why the next line causes a segfault 68 | /// when using the same function more than once 69 | // pixelID-=nodeNumber+1; 70 | current=nullptr; 71 | 72 | lastPixelID=pixelID; 73 | return cache; 74 | } 75 | -------------------------------------------------------------------------------- /plugins/functions/FunctionNode.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTIONNODE_H 2 | #define FUNCTIONNODE_H 3 | 4 | #include "Node.h" 5 | #include "Function.h" 6 | 7 | class FunctionNode: public Node{ 8 | public: 9 | FunctionNode(Function *f); 10 | FunctionNode(); 11 | ~FunctionNode(); 12 | data_t eval(); 13 | static Node* makefromBin(std::istream&); 14 | static Node* makefromText(std::istream&); 15 | static FunctionNode* current; 16 | Function* func; 17 | const uint nodeNumber; 18 | private: 19 | static uint nbNodes; 20 | inline data_t kernel()const{return func->start->eval();} 21 | void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); 22 | void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); 23 | operator bool()const; 24 | void changeNbArgs(uint args); 25 | void toBin(std::ostream&)const override; 26 | void toText(std::ostream&)const override; 27 | }; 28 | 29 | #endif // FUNCTIONNODE_H 30 | -------------------------------------------------------------------------------- /plugins/functions/FunctionPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "FunctionPlugin.h" 2 | 3 | #include "FunctionNode.h" 4 | #include "FunctionManager.h" 5 | 6 | void FunctionPlugin::updateUI(Ui::MainWindow* ui) const{ 7 | QAction* funcAction= new QAction("Function"); 8 | 9 | Workspace* ws=(Workspace*)ui->workspace->scene(); 10 | connect(funcAction,&QAction::triggered,ws,[=]{ 11 | Function* f= FunctionManager::getFunction(); 12 | if(f){ 13 | std::istringstream in(std::to_string(FunctionManager::indexOf(f))); 14 | ws->addNode(Node::nodeMalloc("fun",in)); 15 | } 16 | }); 17 | 18 | ui->menuInsert->addAction(funcAction); 19 | 20 | QAction* fmAction= new QAction("Function Manager"); 21 | connect(fmAction,SIGNAL(triggered(bool)),FunctionManager::instance(),SLOT(exec())); 22 | ui->menuTools->addAction(fmAction); 23 | } 24 | 25 | void FunctionPlugin::init()const{ 26 | Node::makeNodeBinTextMethods["fun"] = {&FunctionNode::makefromBin,&FunctionNode::makefromText}; 27 | Node::makeNodeBinTextMethods["fin"] = 28 | {&Function::FunctionInputNode::makefromBin,&Function::FunctionInputNode::makefromText}; 29 | Node::makeNodeBinTextMethods["fout"] = 30 | {&Function::FunctionOutputNode::makeNode, &Function::FunctionOutputNode::makeNode}; 31 | NodeBox::addTool("fun","Function"); 32 | } 33 | 34 | void FunctionPlugin::toBin(std::ostream &out)const{ 35 | int tmp= FunctionManager::count(); 36 | out.write(reinterpret_cast(&tmp),sizeof(int)); 37 | for(int i=0; itoBin(out); 39 | } 40 | void FunctionPlugin::toText(std::ostream &out)const{ 41 | int tmp= FunctionManager::count(); 42 | out << tmp << '\n'; 43 | for(int i=0; itoText(out); 45 | } 46 | void FunctionPlugin::fromBin(std::istream &in) const{ 47 | FunctionManager::clear(); 48 | int tmp; 49 | in.read(reinterpret_cast(&tmp),sizeof(int)); 50 | for(int i=0;ifromBin(in); 52 | } 53 | void FunctionPlugin::fromText(std::istream &in) const{ 54 | FunctionManager::clear(); 55 | int tmp; 56 | in>>tmp; 57 | for(int i=0;ifromText(in); 59 | } 60 | -------------------------------------------------------------------------------- /plugins/functions/FunctionPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef FUNCPLUGIN_H 2 | #define FUNCPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class FunctionPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const override; 16 | void toBin(std::ostream&)const override; 17 | void toText(std::ostream&)const override; 18 | void fromBin(std::istream&)const override; 19 | void fromText(std::istream&)const override; 20 | inline bool redefineSaveLoad()const override{return true;} 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /plugins/functions/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/functions/arrow.png -------------------------------------------------------------------------------- /plugins/functions/fromToStream.cpp: -------------------------------------------------------------------------------- 1 | #include "FunctionNode.h" 2 | #include "FunctionManager.h" 3 | 4 | Node* Function::FunctionInputNode::makefromBin(std::istream &in){ 5 | int r; 6 | in.read(reinterpret_cast(&r),sizeof(int)); 7 | return new FunctionInputNode(r); 8 | } 9 | Node* Function::FunctionInputNode::makefromText(std::istream &in){ 10 | int r; 11 | in >>r; 12 | return new FunctionInputNode(r); 13 | } 14 | 15 | void Function::FunctionInputNode::toBin(std::ostream&out)const{ 16 | Node::toBin(out); 17 | out.write(reinterpret_cast(&_rank),sizeof(int)); 18 | } 19 | void Function::FunctionInputNode::toText(std::ostream&out)const{ 20 | Node::toText(out); 21 | out <<' '<< _rank; 22 | } 23 | 24 | void Function::toBin(std::ostream& out)const{ 25 | const std::string tmp= text().toStdString(); 26 | out.write(tmp.data(),sizeof(char)*tmp.size()); 27 | out << '\n'; 28 | scene->toBin(out); 29 | out.write(reinterpret_cast(&nbArgs),sizeof(int)); 30 | } 31 | 32 | void Function::toText(std::ostream& out)const{ 33 | out << text().toStdString()<<"\n"; 34 | scene->toText(out); 35 | out << nbArgs << '\n'; 36 | } 37 | 38 | Node* FunctionNode::makefromBin(std::istream&in){ 39 | Function* f; 40 | if(in.peek()!=EOF){ 41 | int i; 42 | in.read(reinterpret_cast(&i),sizeof(int)); 43 | f=FunctionManager::functionAt(i); 44 | }else{ 45 | f=FunctionManager::getFunction(); 46 | if(!f) return nullptr; 47 | } 48 | return new FunctionNode(f); 49 | } 50 | Node* FunctionNode::makefromText(std::istream&in){ 51 | Function* f; 52 | if(in.peek()!=EOF){ 53 | int i; 54 | in >> i; 55 | f=FunctionManager::functionAt(i); 56 | }else{ 57 | f=FunctionManager::getFunction(); 58 | if(!f) return nullptr; 59 | } 60 | return new FunctionNode(f); 61 | } 62 | 63 | void FunctionNode::toBin(std::ostream &out) const{ 64 | Node::toBin(out); 65 | const int tmp= FunctionManager::indexOf(func); 66 | out.write(reinterpret_cast(&tmp),sizeof(int)); 67 | } 68 | void FunctionNode::toText(std::ostream &out) const{ 69 | Node::toText(out); 70 | out <<' '<< FunctionManager::indexOf(func); 71 | } 72 | -------------------------------------------------------------------------------- /plugins/functions/func.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | arrow.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /plugins/functions/functionmanager.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | FunctionManager 4 | 5 | 6 | 7 | 0 8 | 0 9 | 747 10 | 417 11 | 12 | 13 | 14 | Function Manager 15 | 16 | 17 | 18 | 19 | 20 | 21 | 150 22 | 16777215 23 | 24 | 25 | 26 | -1 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 37 | 38 | 39 | 40 | 100 41 | 16777215 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Qt::Vertical 52 | 53 | 54 | 55 | 20 56 | 40 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Add 65 | 66 | 67 | 68 | 69 | 70 | 71 | false 72 | 73 | 74 | Remove 75 | 76 | 77 | 78 | 79 | 80 | 81 | false 82 | 83 | 84 | 85 | 86 | 87 | 88 | Qt::Vertical 89 | 90 | 91 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 92 | 93 | 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Qt::Vertical 102 | 103 | 104 | 105 | 20 106 | 40 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | NodeBox 121 | QToolBox 122 |
NodeBox.h
123 | 1 124 |
125 |
126 | 127 | 128 |
129 | -------------------------------------------------------------------------------- /plugins/image/BitmapNode.cpp: -------------------------------------------------------------------------------- 1 | #include "BitmapNode.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | BitmapNode::BitmapNode(const std::string& filename): 8 | Node("img",70,70,Qt::lightGray,2),path(filename){ 9 | setBMP(filename); 10 | } 11 | 12 | BitmapNode::~BitmapNode(){ 13 | delete bmp; 14 | } 15 | 16 | void BitmapNode::setBMP(const std::string& filename){ 17 | path=filename; 18 | bmp= new QPixmap(QString::fromStdString(filename)); 19 | bmpWidth=bmp->width(); 20 | bmpHeight=bmp->height(); 21 | } 22 | 23 | data_t BitmapNode::kernel()const{ 24 | if(!bmp) return 0xff000000; 25 | int g0 = double(iNodes[0]->eval())*bmpWidth; 26 | int g1 = double(iNodes[1]->eval())*bmpHeight; 27 | if(g0<0 || g0>=bmpWidth || g1<0 || g1>=bmpHeight) 28 | return 0xff000000; 29 | return bmp->toImage().pixel(g0,g1); 30 | } 31 | 32 | QImage BitmapNode::scaleImage(uint w, uint h) const{ 33 | QImage image(w,h,QImage::Format_ARGB32_Premultiplied); 34 | for(uint i=0; itoImage().pixel(double(i)/w*bmpWidth,double(j)/h*bmpHeight)); 37 | return image; 38 | } 39 | 40 | void BitmapNode::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*){ 41 | pen.setWidth(isSelected()?2:1); 42 | painter->setPen(pen); 43 | painter->drawLine(QPointF(0,height/(3.0)),QPointF(socketSize,height/(3.0))); 44 | painter->drawLine(QPointF(0,2*height/(3.0)),QPointF(socketSize,2*height/(3.0))); 45 | painter->drawRect(socketSize,0,width,height); 46 | QRectF rect= boundingRect(); 47 | painter->drawLine(rect.center()+QPointF(rect.width()/2,0),rect.center()+QPointF(rect.width()/2-socketSize,0)); 48 | if(bmp->isNull()){ 49 | painter->drawText(boundingRect().center()+QPointF(-20,-2),"Bitmap"); 50 | painter->drawText(boundingRect().center()+QPointF(-28,12),"not found"); 51 | } 52 | else 53 | painter->drawImage(socketSize+1,1,scaleImage(width-1,height-1)); 54 | } 55 | 56 | void BitmapNode::contextMenuEvent(QGraphicsSceneContextMenuEvent* event){ 57 | menu=new QMenu; 58 | connect(menu->addAction(QString("Choose image")), &QAction::triggered,this,&BitmapNode::changeBMP); 59 | menu->addSeparator(); 60 | Node::contextMenuEvent(event); 61 | } 62 | 63 | void BitmapNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *){ 64 | changeBMP(); 65 | } 66 | 67 | void BitmapNode::changeBMP(){ 68 | QString f= QFileDialog::getOpenFileName(0,"Choose Image",".","Images (*.bmp)"); 69 | if(f.isNull())return; 70 | setBMP(f.toStdString()); 71 | updateVal(); 72 | emit sm.updateOutputs(); 73 | update(); 74 | } 75 | -------------------------------------------------------------------------------- /plugins/image/BitmapNode.h: -------------------------------------------------------------------------------- 1 | #ifndef BITMAPNODE_H 2 | #define BITMAPNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class BitmapNode : public Node{ 7 | public: 8 | BitmapNode(const std::string &filename); 9 | ~BitmapNode(); 10 | void setBMP(const std::string &filename); 11 | static Node* makeFromBin(std::istream &); 12 | static Node* makeFromText(std::istream &); 13 | private: 14 | std::string path; 15 | QPixmap *bmp; 16 | int bmpWidth, bmpHeight; 17 | data_t kernel()const; 18 | void paint(QPainter *painter, 19 | const QStyleOptionGraphicsItem* option, 20 | QWidget* widget); 21 | void contextMenuEvent(QGraphicsSceneContextMenuEvent* event); 22 | void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); 23 | QImage scaleImage(uint w, uint h)const; 24 | void toBin(std::ostream &)const override; 25 | void toText(std::ostream &)const override; 26 | private slots: 27 | void changeBMP(); 28 | }; 29 | 30 | #endif // BITMAPNODE_H 31 | -------------------------------------------------------------------------------- /plugins/image/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(ImagePlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 9 | qt5_add_resources(QRC image.qrc) 10 | add_custom_target(image_qrc DEPENDS ${QRC}) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 13 | 14 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 15 | 16 | add_library(${PROJECT_NAME} SHARED ImagePlugin.cpp ImagePlugin.h) 17 | add_library(image 18 | fromToStream.cpp 19 | BitmapNode.cpp 20 | BitmapNode.h) 21 | 22 | target_link_libraries(${PROJECT_NAME} image data_t ${QRC}) 23 | add_dependencies(${PROJECT_NAME} image_qrc) 24 | -------------------------------------------------------------------------------- /plugins/image/ImagePlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "ImagePlugin.h" 2 | #include "BitmapNode.h" 3 | 4 | void ImagePlugin::updateUI(Ui::MainWindow* ui) const{ 5 | QAction* imageAction= new QAction(QIcon(":/image.png"),"Image"); 6 | 7 | Workspace* ws= (Workspace*)ui->workspace->scene(); 8 | connect(imageAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("img"));}); 9 | 10 | ui->menuInsert->addAction(imageAction); 11 | 12 | } 13 | 14 | void ImagePlugin::init()const{ 15 | Node::makeNodeBinTextMethods["img"] = {&BitmapNode::makeFromBin,&BitmapNode::makeFromText}; 16 | NodeBox::addTool("img","Image",QIcon(":/image.png")); 17 | } 18 | -------------------------------------------------------------------------------- /plugins/image/ImagePlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEPLUGIN_H 2 | #define IMAGEPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class ImagePlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/image/fromToStream.cpp: -------------------------------------------------------------------------------- 1 | #include "BitmapNode.h" 2 | #include 3 | 4 | static Node* askForBMP(){ 5 | QString filename = QFileDialog::getOpenFileName(0,"Choose Image",".","Images (*.bmp)"); 6 | if(filename.isNull()) return nullptr; 7 | return new BitmapNode(filename.toStdString()); 8 | } 9 | 10 | Node* BitmapNode::makeFromBin(std::istream&in){ 11 | if(in.peek()!=EOF){ 12 | std::string path; 13 | in >> path; 14 | in.ignore(1); 15 | return new BitmapNode(path); 16 | } 17 | return askForBMP(); 18 | } 19 | Node* BitmapNode::makeFromText(std::istream&in){ 20 | if(in.peek()!=EOF){ 21 | std::string path; 22 | in >> path; 23 | return new BitmapNode(path); 24 | } 25 | return askForBMP(); 26 | } 27 | 28 | void BitmapNode::toBin(std::ostream &out) const{ 29 | Node::toBin(out); 30 | out <<' '<< path << '\n'; 31 | } 32 | void BitmapNode::toText(std::ostream &out) const{ 33 | Node::toText(out); 34 | out <<' '<< path; 35 | } 36 | -------------------------------------------------------------------------------- /plugins/image/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/image/image.png -------------------------------------------------------------------------------- /plugins/image/image.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | image.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /plugins/io/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(IOPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | set(CMAKE_AUTOUIC ON) 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 10 | qt5_add_resources(QRC io.qrc) 11 | add_custom_target(io_qrc DEPENDS ${QRC}) 12 | 13 | qt5_wrap_ui(UI_HEADERS exportimagedialog.ui) 14 | 15 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 16 | 17 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 18 | 19 | add_library(${PROJECT_NAME} SHARED IoPlugin.cpp IoPlugin.h) 20 | add_library(io 21 | InputNode.cpp 22 | OutputNode.cpp 23 | ExportImageDialog.cpp 24 | InputNode.h 25 | OutputNode.h 26 | ExportImageDialog.h 27 | ${UI_HEADERS}) 28 | 29 | target_link_libraries(${PROJECT_NAME} io data_t ${QRC}) 30 | add_dependencies(${PROJECT_NAME} io_qrc) 31 | -------------------------------------------------------------------------------- /plugins/io/ExportImageDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "ExportImageDialog.h" 2 | #include "ui_exportimagedialog.h" 3 | 4 | #include 5 | 6 | ExportImageDialog::ExportImageDialog(QWidget *parent) : 7 | QDialog(parent), 8 | ui(new Ui::ExportImageDialog){ 9 | ui->setupUi(this); 10 | } 11 | 12 | ExportImageDialog::~ExportImageDialog(){ 13 | delete ui; 14 | } 15 | 16 | void ExportImageDialog::exportBMP(OutputNode *node){ 17 | QString f= QFileDialog::getSaveFileName(0,"Export Image",".","Images (*.bmp)"); 18 | if(f.isNull()) return; 19 | if(!f.endsWith(".bmp")) 20 | f.append(".bmp"); 21 | ExportImageDialog dial; 22 | if(!dial.exec()) return; 23 | int w = dial.ui->widthBox->value(); 24 | int h = dial.ui->heightBox->value(); 25 | QPixmap::fromImage(node->output->renderImage(w,h)).save(f); 26 | } 27 | -------------------------------------------------------------------------------- /plugins/io/ExportImageDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPORTIMAGEDIALOG_H 2 | #define EXPORTIMAGEDIALOG_H 3 | 4 | #include 5 | #include "OutputNode.h" 6 | 7 | namespace Ui { 8 | class ExportImageDialog; 9 | } 10 | 11 | class ExportImageDialog : public QDialog{ 12 | Q_OBJECT 13 | 14 | public: 15 | explicit ExportImageDialog(QWidget *parent = 0); 16 | ~ExportImageDialog(); 17 | static void exportBMP(OutputNode *node); 18 | 19 | private: 20 | Ui::ExportImageDialog *ui; 21 | }; 22 | 23 | #endif // EXPORTIMAGEDIALOG_H 24 | -------------------------------------------------------------------------------- /plugins/io/InputNode.cpp: -------------------------------------------------------------------------------- 1 | #include "InputNode.h" 2 | 3 | #include 4 | 5 | double InputNode::input_x; 6 | double InputNode::input_y; 7 | double RatioNode::ratio; 8 | InputNode::InputNode(const std::string& type):Node(type,70,50,Qt::lightGray){} 9 | XNode::XNode():InputNode("x"){} 10 | YNode::YNode():InputNode("y"){} 11 | RatioNode::RatioNode():Node("ratio",70,50,Qt::lightGray){ 12 | constant=true; 13 | connect(&sm,SIGNAL(updateRatio()),this,SLOT(updateVal())); 14 | } 15 | RatioNode::~RatioNode(){ 16 | disconnect(&sm,SIGNAL(updateRatio()),this,SLOT(updateVal())); 17 | } 18 | 19 | void InputNode::paint(QPainter *painter, const QStyleOptionGraphicsItem*option, QWidget*widget){ 20 | Node::paint(painter,option,widget); 21 | } 22 | 23 | void XNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 24 | InputNode::paint(painter,option,widget); 25 | QRectF rect=boundingRect(); 26 | painter->drawText(rect.center()+QPointF(-5,3),"X"); 27 | } 28 | void YNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 29 | InputNode::paint(painter,option,widget); 30 | QRectF rect=boundingRect(); 31 | painter->drawText(rect.center()+QPoint(-5,3),"Y"); 32 | } 33 | 34 | void RatioNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 35 | Node::paint(painter,option,widget); 36 | QRectF rect=boundingRect(); 37 | painter->drawText(rect.x()+rect.width()/3,rect.y()+rect.height()/2+3,"W/H"); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /plugins/io/InputNode.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUTNODE_H 2 | #define INPUTNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class InputNode:public Node{ 7 | protected: 8 | InputNode(const std::string &); 9 | virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*); 10 | static double input_x, input_y; 11 | friend class OutputNode; 12 | }; 13 | 14 | class XNode:public InputNode{ 15 | public: 16 | XNode(); 17 | inline static Node* makeNode(std::istream&){return new XNode;} 18 | private: 19 | void paint(QPainter* painter, 20 | const QStyleOptionGraphicsItem* option, 21 | QWidget* widget); 22 | inline data_t kernel()const{return input_x;} 23 | }; 24 | 25 | class YNode:public InputNode{ 26 | public: 27 | YNode(); 28 | inline static Node* makeNode(std::istream&){return new YNode;} 29 | private: 30 | void paint(QPainter* painter, 31 | const QStyleOptionGraphicsItem* option, 32 | QWidget* widget); 33 | inline data_t kernel()const{return input_y;} 34 | }; 35 | 36 | class RatioNode:public Node{ 37 | void paint(QPainter* painter, 38 | const QStyleOptionGraphicsItem* option, 39 | QWidget* widget); 40 | static double ratio; 41 | inline data_t kernel()const{return ratio;} 42 | friend class OutputNode; 43 | public: 44 | RatioNode(); 45 | ~RatioNode(); 46 | inline static Node* makeNode(std::istream&){return new RatioNode;} 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /plugins/io/IoPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "IoPlugin.h" 2 | #include "Node.h" 3 | #include "InputNode.h" 4 | #include "OutputNode.h" 5 | #include "ExportImageDialog.h" 6 | 7 | void IoPlugin::updateUI(Ui::MainWindow* ui) const{ 8 | QMenu* ioMenu = new QMenu("Input/Output",ui->menuInsert); 9 | ui->menuInsert->addAction(ioMenu->menuAction()); 10 | QAction* xAction= new QAction(QIcon(":/x.png"),"X"); 11 | QAction* yAction= new QAction(QIcon(":/y.png"),"Y"); 12 | QAction* ratioAction= new QAction("Ratio"); 13 | QAction* outAction= new QAction(QIcon(":/output.png"),"Output"); 14 | 15 | Workspace* ws=(Workspace*)ui->workspace->scene(); 16 | connect(xAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("x"));}); 17 | connect(yAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("y"));}); 18 | connect(ratioAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("ratio"));}); 19 | connect(outAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("out"));}); 20 | 21 | ioMenu->addAction(xAction); 22 | ioMenu->addAction(yAction); 23 | ioMenu->addAction(ratioAction); 24 | ioMenu->addAction(outAction); 25 | 26 | QAction* exportAction= new QAction("Export"); 27 | exportAction->setShortcut(QKeySequence("Ctrl+E")); 28 | connect(exportAction,&QAction::triggered,ws,[=]{ 29 | for(const auto& node: ws->selectedItems()){ 30 | OutputNode* out = (OutputNode*)node; 31 | if(out->_type=="out" && *out) 32 | ExportImageDialog::exportBMP(out); 33 | } 34 | }); 35 | ui->menuFile->insertAction(ui->actionOpen,exportAction); 36 | } 37 | 38 | void IoPlugin::init()const{ 39 | Node::makeNodeBinTextMethods["x"] = {&XNode::makeNode,&XNode::makeNode}; 40 | Node::makeNodeBinTextMethods["y"] = {&YNode::makeNode,&YNode::makeNode}; 41 | Node::makeNodeBinTextMethods["ratio"]= {&RatioNode::makeNode,&RatioNode::makeNode}; 42 | Node::makeNodeBinTextMethods["out"]= {&OutputNode::makeNode,&OutputNode::makeNode}; 43 | 44 | NodeBox::addTool("x","X",QIcon(":/x.png")); 45 | NodeBox::addTool("y","Y",QIcon(":/y.png")); 46 | NodeBox::addTool("ratio","Width/Height"); 47 | NodeBox::addTool("out","Output",QIcon(":/output.png")); 48 | } 49 | -------------------------------------------------------------------------------- /plugins/io/IoPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef IOPLUGIN_H 2 | #define IOPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class IoPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const override; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/io/OutputNode.cpp: -------------------------------------------------------------------------------- 1 | #include "OutputNode.h" 2 | 3 | #include 4 | #include "InputNode.h" 5 | 6 | OutputNode::RenderArea::RenderArea(OutputNode *node, QWidget *parent):QDockWidget(parent){ 7 | start=node; 8 | setFeatures(0); 9 | setWindowTitle("Output "+QString::number(start->outputNumber)); 10 | } 11 | 12 | QImage OutputNode::RenderArea::renderImage(int w, int h){ 13 | QImage image(w,h ,QImage::Format_ARGB32_Premultiplied); 14 | RatioNode::ratio=double(w)/h; 15 | Node::widthByHeight=w*h; 16 | emit sm.updateRatio(); 17 | for(int i=0;ieval()); 23 | } 24 | return image; 25 | } 26 | 27 | void OutputNode::RenderArea::paintEvent(QPaintEvent *){ 28 | if(*start) 29 | QPainter(this).drawImage(0,0,renderImage(width(),height())); 30 | } 31 | 32 | uint OutputNode::outputs=0; 33 | 34 | void OutputNode::RenderArea::closeEvent(QCloseEvent*){ 35 | start->inside=true; 36 | start->update(); 37 | } 38 | void OutputNode::RenderArea::resizeEvent(QResizeEvent *){ 39 | RatioNode::ratio=double(width())/height(); 40 | Node::widthByHeight=width()*height(); 41 | emit sm.updateRatio(); 42 | } 43 | 44 | OutputNode::OutputNode():Node("out",50, 50, Qt::white,1,true){ 45 | outputNumber=outputs++; 46 | output= new RenderArea(this); 47 | connect(&sm,&SignalManager::updateOutputs,this,&OutputNode::updateOutput); 48 | } 49 | 50 | OutputNode::~OutputNode(){ 51 | disconnect(&sm,&SignalManager::updateOutputs,this,&OutputNode::updateOutput); 52 | delete output; 53 | outputs--; 54 | } 55 | 56 | data_t OutputNode::kernel()const{ 57 | return iNodes[0]->eval(); 58 | } 59 | 60 | void OutputNode::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget){ 61 | pen.setColor(isSelected()?Qt::darkGreen:Qt::black); 62 | if(inside){ 63 | pen.setWidth(isSelected()?2:1); 64 | painter->setPen(pen); 65 | painter->drawLine(QPointF(0,height/2.0),QPointF(socketSize,height/2.0)); 66 | painter->drawRect(QRectF(socketSize,0,width,height)); 67 | if(*this) 68 | painter->drawImage(socketSize+1,1,output->renderImage(width-1,height-1)); 69 | }else{ 70 | Node::paint(painter, option, widget); 71 | painter->setFont(QFont("",8)); 72 | painter->drawText(boundingRect().center()-QPoint(18,-2),"Output "+QString::number(outputNumber)); 73 | } 74 | } 75 | 76 | void OutputNode::updateOutput(){ 77 | update(); 78 | output->update(); 79 | } 80 | 81 | void OutputNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *){ 82 | if(inside) 83 | output->show(); 84 | else 85 | output->close(); 86 | inside=!inside; 87 | update(); 88 | } 89 | -------------------------------------------------------------------------------- /plugins/io/OutputNode.h: -------------------------------------------------------------------------------- 1 | #ifndef OutputNODE_H 2 | #define OutputNODE_H 3 | 4 | #include "Node.h" 5 | #include 6 | 7 | class OutputNode : public Node{ 8 | public: 9 | OutputNode(); 10 | ~OutputNode(); 11 | class RenderArea : public QDockWidget{ 12 | public: 13 | RenderArea(OutputNode* node,QWidget* parent=0); 14 | QImage renderImage(int w,int h); 15 | private: 16 | OutputNode *start; 17 | void closeEvent(QCloseEvent *); 18 | void resizeEvent(QResizeEvent*); 19 | void paintEvent(QPaintEvent*); 20 | }; 21 | inline static Node* makeNode(std::istream&){return new OutputNode;} 22 | private slots: 23 | void updateOutput(); 24 | private: 25 | RenderArea *output; 26 | bool inside=true; 27 | uint outputNumber; 28 | static uint outputs; 29 | data_t kernel()const; 30 | void paint(QPainter* painter, 31 | const QStyleOptionGraphicsItem* option, 32 | QWidget* widget); 33 | void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); 34 | friend class ExportImageDialog; 35 | }; 36 | #endif // RENDERNODE_H 37 | -------------------------------------------------------------------------------- /plugins/io/exportimagedialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ExportImageDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 401 10 | 134 11 | 12 | 13 | 14 | Choose dimension 15 | 16 | 17 | 18 | 19 | 20 | 1 21 | 22 | 23 | 1000000 24 | 25 | 26 | 27 | 28 | 29 | 30 | Qt::Horizontal 31 | 32 | 33 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 34 | 35 | 36 | 37 | 38 | 39 | 40 | 1 41 | 42 | 43 | 1000000 44 | 45 | 46 | 47 | 48 | 49 | 50 | Width : 51 | 52 | 53 | 54 | 55 | 56 | 57 | Height : 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | buttonBox 67 | accepted() 68 | ExportImageDialog 69 | accept() 70 | 71 | 72 | 248 73 | 254 74 | 75 | 76 | 157 77 | 274 78 | 79 | 80 | 81 | 82 | buttonBox 83 | rejected() 84 | ExportImageDialog 85 | reject() 86 | 87 | 88 | 316 89 | 260 90 | 91 | 92 | 286 93 | 274 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /plugins/io/io.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | output.png 4 | x.png 5 | y.png 6 | 7 | 8 | -------------------------------------------------------------------------------- /plugins/io/output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/io/output.png -------------------------------------------------------------------------------- /plugins/io/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/io/x.png -------------------------------------------------------------------------------- /plugins/io/y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/io/y.png -------------------------------------------------------------------------------- /plugins/logic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(LogicPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 9 | qt5_add_resources(QRC logic.qrc) 10 | add_custom_target(logic_qrc DEPENDS ${QRC}) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 13 | 14 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 15 | 16 | add_library(${PROJECT_NAME} SHARED LogicPlugin.cpp LogicPlugin.h) 17 | add_library(logic LogicNode.cpp LogicNode.h) 18 | 19 | target_link_libraries(${PROJECT_NAME} logic data_t ${QRC}) 20 | add_dependencies(${PROJECT_NAME} logic_qrc) 21 | -------------------------------------------------------------------------------- /plugins/logic/LogicNode.cpp: -------------------------------------------------------------------------------- 1 | #include "LogicNode.h" 2 | 3 | #include 4 | 5 | LogicNode::LogicNode(const std::string &type, unsigned n):Node(type,50,50,QColor(255,180,180),n){} 6 | 7 | ORNode::ORNode():LogicNode("or",2){} 8 | ANDNode::ANDNode():LogicNode("and",2){} 9 | XORNode::XORNode():LogicNode("xor",2){} 10 | NOTNode::NOTNode():LogicNode("not",1){} 11 | 12 | void ORNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 13 | Node::paint(painter,option, widget); 14 | painter->drawText(boundingRect().center()-QPoint(10,-2),"OR"); 15 | } 16 | void ANDNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 17 | Node::paint(painter,option, widget); 18 | painter->drawText(boundingRect().center()-QPoint(12,-2),"AND"); 19 | } 20 | void XORNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 21 | Node::paint(painter,option, widget); 22 | painter->drawText(boundingRect().center()-QPoint(12,-2),"XOR"); 23 | } 24 | void NOTNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 25 | Node::paint(painter,option, widget); 26 | painter->drawText(boundingRect().center()-QPoint(12,-2),"NOT"); 27 | } 28 | 29 | data_t ORNode::kernel()const{ 30 | return iNodes[0]->eval() || iNodes[1]->eval(); 31 | } 32 | data_t ANDNode::kernel()const{ 33 | return iNodes[0]->eval() && iNodes[1]->eval(); 34 | } 35 | data_t XORNode::kernel()const{ 36 | return bool(bool(iNodes[0]->eval()) ^ bool(iNodes[1]->eval())); 37 | } 38 | data_t NOTNode::kernel()const{ 39 | return !iNodes[0]->eval(); 40 | } 41 | -------------------------------------------------------------------------------- /plugins/logic/LogicNode.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGICNODE_H 2 | #define LOGICNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class LogicNode:public Node{ 7 | protected: 8 | LogicNode(const std::string &type, unsigned n); 9 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)=0; 10 | }; 11 | 12 | class ORNode:public LogicNode{ 13 | public: 14 | ORNode(); 15 | inline static Node* makeNode(std::istream&){return new ORNode;} 16 | private: 17 | data_t kernel()const; 18 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 19 | }; 20 | 21 | class ANDNode:public LogicNode{ 22 | public: 23 | ANDNode(); 24 | inline static Node* makeNode(std::istream&){return new ANDNode;} 25 | private: 26 | data_t kernel()const; 27 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 28 | }; 29 | 30 | class XORNode:public LogicNode{ 31 | public: 32 | XORNode(); 33 | inline static Node* makeNode(std::istream&){return new XORNode;} 34 | private: 35 | data_t kernel()const; 36 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 37 | }; 38 | 39 | class NOTNode:public LogicNode{ 40 | public: 41 | NOTNode(); 42 | inline static Node* makeNode(std::istream&){return new NOTNode;} 43 | private: 44 | data_t kernel()const; 45 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 46 | }; 47 | #endif 48 | -------------------------------------------------------------------------------- /plugins/logic/LogicPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "LogicPlugin.h" 2 | #include "LogicNode.h" 3 | 4 | void LogicPlugin::updateUI(Ui::MainWindow* ui) const{ 5 | QMenu* logicMenu = new QMenu("Logic",ui->menuInsert); 6 | ui->menuInsert->addAction(logicMenu->menuAction()); 7 | QAction* andAction= new QAction(QIcon(":/and.png"), "And"); 8 | QAction* orAction= new QAction(QIcon(":/or.png"), "Or"); 9 | QAction* xorAction= new QAction(QIcon(":/xor.png"), "Xor"); 10 | QAction* notAction= new QAction(QIcon(":/not.png"), "Not"); 11 | 12 | Workspace* ws=(Workspace*)ui->workspace->scene(); 13 | connect(andAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("and"));}); 14 | connect(orAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("or"));}); 15 | connect(xorAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("xor"));}); 16 | connect(notAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("not"));}); 17 | 18 | logicMenu->addAction(andAction); 19 | logicMenu->addAction(orAction); 20 | logicMenu->addAction(xorAction); 21 | logicMenu->addAction(notAction); 22 | 23 | } 24 | 25 | void LogicPlugin::init()const{ 26 | Node::makeNodeBinTextMethods["and"] = {&ANDNode::makeNode,&ANDNode::makeNode}; 27 | Node::makeNodeBinTextMethods["or"] = {&ORNode::makeNode ,&ORNode::makeNode }; 28 | Node::makeNodeBinTextMethods["xor"] = {&XORNode::makeNode,&XORNode::makeNode}; 29 | Node::makeNodeBinTextMethods["not"] = {&NOTNode::makeNode,&NOTNode::makeNode}; 30 | 31 | NodeBox::addTool("and","And",QIcon(":/and.png"),"Logic"); 32 | NodeBox::addTool("or","Or",QIcon(":/or.png"),"Logic"); 33 | NodeBox::addTool("xor","Xor",QIcon(":/xor.png"),"Logic"); 34 | NodeBox::addTool("not","Not",QIcon(":/not.png"),"Logic"); 35 | } 36 | -------------------------------------------------------------------------------- /plugins/logic/LogicPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef LOGICPLUGIN_H 2 | #define LOGICPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class LogicPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/logic/and.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/logic/and.png -------------------------------------------------------------------------------- /plugins/logic/logic.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | and.png 4 | not.png 5 | or.png 6 | xor.png 7 | 8 | 9 | -------------------------------------------------------------------------------- /plugins/logic/not.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/logic/not.png -------------------------------------------------------------------------------- /plugins/logic/or.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/logic/or.png -------------------------------------------------------------------------------- /plugins/logic/xor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/logic/xor.png -------------------------------------------------------------------------------- /plugins/lut/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(LUTPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 8 | 9 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 10 | 11 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 12 | 13 | add_library(dialog 14 | dialog/lut_dialog.cpp 15 | dialog/lut_dialog.h) 16 | add_library(${PROJECT_NAME} SHARED LUTPlugin.cpp LUTPlugin.h) 17 | add_library(lut fromToStream.cpp LUTNode.cpp Gradient.cpp LUTNode.h Gradient.h) 18 | 19 | target_link_libraries(${PROJECT_NAME} lut data_t dialog) 20 | -------------------------------------------------------------------------------- /plugins/lut/Gradient.cpp: -------------------------------------------------------------------------------- 1 | #include "Gradient.h" 2 | #include 3 | /*Uint32 = [.ALPHA..][...RED..][.GREEN..][..BLUE..]*/ 4 | 5 | void getRGB(unsigned color, uint8_t &r, uint8_t &g, uint8_t &b){ 6 | b=color; 7 | color>>=8; 8 | g=color; 9 | color>>=8; 10 | r=color; 11 | } 12 | 13 | unsigned makeRGB(uint8_t r, uint8_t g, uint8_t b){ 14 | unsigned c=0xff; 15 | c<<=8; c|=r; 16 | c<<=8; c|=g; 17 | c<<=8; c|=b; 18 | return c; 19 | } 20 | 21 | Gradient::Gradient(){} 22 | Gradient::Gradient(const Gradient &p){ 23 | if(!p.empty()){ 24 | first= new color(p.first); 25 | color* tmp= first; 26 | for(color*tmpOther=p.first->next;tmpOther;tmpOther=tmpOther->next){ 27 | tmp->next= new color(tmpOther); 28 | tmp->next->prev=tmp; 29 | tmp->next->gr=this; 30 | tmp=tmp->next; 31 | } 32 | last=tmp; 33 | } 34 | } 35 | 36 | Gradient::color::color(Gradient*g,unsigned c, double a):gr(g),clr(c), alpha(a){} 37 | Gradient::color::color(color *c):clr(c->clr),alpha(c->alpha){} 38 | void Gradient::color::updateAlpha(double newAlpha){ 39 | if(next && newAlpha>next->alpha){ 40 | if(this==gr->first) 41 | gr->first=next; 42 | else prev->next=next; 43 | next->prev=prev; 44 | 45 | color* tmp= next->next; 46 | while(tmp&&newAlpha>tmp->alpha) 47 | tmp=tmp->next; 48 | if(tmp){ 49 | prev=tmp->prev; 50 | tmp->prev=this; 51 | prev->next=this; 52 | next=tmp; 53 | }else{ 54 | prev=gr->last; 55 | prev->next=this; 56 | gr->last=this; 57 | next=nullptr; 58 | } 59 | }else if(prev && newAlphaalpha){ 60 | if(this==gr->last) 61 | gr->last=prev; 62 | else next->prev=prev; 63 | prev->next=next; 64 | 65 | color* tmp= prev->prev; 66 | while(tmp&&newAlphaalpha) 67 | tmp=tmp->prev; 68 | if(tmp){ 69 | next=tmp->next; 70 | tmp->next=this; 71 | next->prev=this; 72 | prev=tmp; 73 | }else{ 74 | next=gr->first; 75 | next->prev=this; 76 | gr->first=this; 77 | prev=nullptr; 78 | } 79 | } 80 | alpha=newAlpha; 81 | } 82 | 83 | bool Gradient::empty()const{ 84 | return first==nullptr; 85 | } 86 | 87 | Gradient::color *Gradient::add(unsigned color, double alpha){ 88 | if(alpha<0)alpha=0; 89 | if(alpha>1)alpha=1; 90 | Gradient::color* n= new Gradient::color(this,color, alpha); 91 | if(empty()) 92 | first=last=n; 93 | else{ 94 | if(first->alpha > alpha){ 95 | n->next=first; 96 | first->prev=n; 97 | first=n; 98 | } 99 | else{ 100 | for(auto it =first; it !=nullptr; it=it->next) 101 | if(it->alpha >= alpha){ 102 | struct color* before= it->prev; 103 | it->prev=n; 104 | before->next=n; 105 | n->prev=before; 106 | n->next=it; 107 | return n; 108 | } 109 | last->next=n; 110 | n->prev=last; 111 | last=n; 112 | } 113 | } 114 | return n; 115 | } 116 | 117 | unsigned Gradient::average(color c1, color c2, double i){ 118 | i=(i-c1.alpha)/(c2.alpha-c1.alpha); 119 | uint8_t r1,g1,b1, r2,g2,b2; 120 | getRGB(c1.clr, r1, g1, b1); 121 | getRGB(c2.clr, r2, g2, b2); 122 | 123 | return makeRGB(r2*i+(1.0-i)*r1 124 | ,g2*i+(1.0-i)*g1 125 | ,b2*i+(1.0-i)*b1); 126 | } 127 | 128 | unsigned Gradient::operator[](double alpha)const{ 129 | if(empty()) return 0xff000000; 130 | if(alpha<0) return first->clr; 131 | if(alphaalpha) return first->clr; 132 | for(auto it= first->next; it!= nullptr; it=it->next){ 133 | if(alphaalpha) 134 | return average(*it->prev, *it, alpha); 135 | } 136 | return last->clr; 137 | } 138 | 139 | void Gradient::remove(color *c){ 140 | if(!c)return; 141 | if(c==first) first=c->next; 142 | else c->prev->next=c->next; 143 | if(c==last) last=c->prev; 144 | else c->next->prev=c->prev; 145 | delete c; 146 | } 147 | Gradient::~Gradient(){ 148 | while (!empty()) remove(first); 149 | } 150 | -------------------------------------------------------------------------------- /plugins/lut/Gradient.h: -------------------------------------------------------------------------------- 1 | #ifndef GRADIENT_H 2 | #define GRADIENT_H 3 | 4 | #include 5 | 6 | class Gradient{ 7 | private: 8 | struct color{ 9 | color(Gradient* p,unsigned c, double a); 10 | color(color*); 11 | Gradient* gr; 12 | struct color* next=nullptr; 13 | struct color* prev=nullptr; 14 | const unsigned clr; 15 | double alpha; 16 | void updateAlpha(double newAlpha); 17 | }; 18 | void remove(color* c); 19 | static unsigned average(color c1, color c2, double i); 20 | struct color*first=nullptr; 21 | struct color*last=nullptr; 22 | friend class LutCursor; 23 | friend class LutView; 24 | friend std::ostream& operator<<(std::ostream&,const Gradient&); 25 | public: 26 | Gradient(); 27 | Gradient(const Gradient&); 28 | ~Gradient(); 29 | color* add(unsigned color, double alpha); 30 | unsigned operator[](double alpha)const; 31 | bool empty()const; 32 | void toBin(std::ostream&)const; 33 | void toText(std::ostream&)const; 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /plugins/lut/LUTNode.cpp: -------------------------------------------------------------------------------- 1 | #include "LUTNode.h" 2 | 3 | #include "dialog/lut_dialog.h" 4 | #include 5 | 6 | LUTNode::LUTNode(Gradient *g): Node("lut",140,70,Qt::white,1), gradient(*g){} 7 | 8 | data_t LUTNode::kernel()const{ 9 | return gradient[iNodes[0]->eval()]; 10 | } 11 | 12 | void LUTNode::paint(QPainter *painter, const QStyleOptionGraphicsItem* option, QWidget* widget){ 13 | Node::paint(painter, option, widget); 14 | for(uint i=socketSize*2; isetPen(gradient[i/(double)width]); 16 | painter->drawLine(QPoint(i,10),QPoint(i,height-10)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plugins/lut/LUTNode.h: -------------------------------------------------------------------------------- 1 | #ifndef LUTNODE_H 2 | #define LUTNODE_H 3 | 4 | #include "Gradient.h" 5 | #include "Node.h" 6 | 7 | class LUTNode:public Node{ 8 | public: 9 | explicit LUTNode(Gradient *p); 10 | static Node* makeFromBin(std::istream&); 11 | static Node* makeFromText(std::istream&); 12 | private: 13 | void paint(QPainter* painter, const QStyleOptionGraphicsItem*option, QWidget*widget); 14 | data_t kernel()const; 15 | Gradient gradient; 16 | void toBin(std::ostream &)const override; 17 | void toText(std::ostream &)const override; 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /plugins/lut/LUTPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "LUTPlugin.h" 2 | #include "LUTNode.h" 3 | 4 | void LUTPlugin::updateUI(Ui::MainWindow* ui) const{ 5 | QAction* lutAction= new QAction("LUT"); 6 | 7 | Workspace* ws=(Workspace*)ui->workspace->scene(); 8 | connect(lutAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("lut"));}); 9 | 10 | ui->menuInsert->addAction(lutAction); 11 | } 12 | 13 | void LUTPlugin::init()const{ 14 | Node::makeNodeBinTextMethods["lut"] = {&LUTNode::makeFromBin,&LUTNode::makeFromText}; 15 | NodeBox::addTool("lut","LUT","Color"); 16 | } 17 | -------------------------------------------------------------------------------- /plugins/lut/LUTPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef LUTPLUGIN_H 2 | #define LUTPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class LUTPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const override; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/lut/dialog/lut_dialog.cpp: -------------------------------------------------------------------------------- 1 | #include "lut_dialog.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | LutDialog::LutDialog(QWidget *parent) : 11 | QDialog(parent){ 12 | QVBoxLayout* vbl= new QVBoxLayout; 13 | QColorDialog* colorDialog= new QColorDialog; 14 | colorDialog->setWindowFlag(Qt::Widget); 15 | colorDialog->setOptions(QColorDialog::DontUseNativeDialog|QColorDialog::NoButtons); 16 | QDialogButtonBox* buttons= new QDialogButtonBox(this); 17 | buttons->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); 18 | 19 | buttons->setWindowFlag(Qt::Widget); 20 | vbl->setMargin(2); 21 | vbl->addWidget(colorDialog); 22 | view= new LutView(this); 23 | vbl->addWidget(view); 24 | vbl->addWidget(buttons); 25 | setLayout(vbl); 26 | 27 | connect(buttons,SIGNAL(accepted()),this,SLOT(accept())); 28 | connect(buttons,SIGNAL(rejected()),this,SLOT(reject())); 29 | connect(colorDialog,SIGNAL(accepted()),this,SLOT(accept())); 30 | connect(colorDialog,SIGNAL(rejected()),this,SLOT(reject())); 31 | setFixedSize(minimumSize()); 32 | } 33 | Gradient* LutDialog::getGradient(){ 34 | LutDialog dial; 35 | if(dial.exec()) 36 | return new Gradient(dial.view->grd); 37 | return nullptr; 38 | } 39 | 40 | LutDialog::~LutDialog(){ 41 | delete view; 42 | } 43 | 44 | LutCursor* LutView::curs; 45 | LutView::LutView(QWidget* parent):QGraphicsView(parent){ 46 | setScene(_scene=new QGraphicsScene); 47 | setAcceptDrops(true); 48 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 49 | setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 50 | background= new LutBackground(&grd); 51 | _scene->addItem(background); 52 | } 53 | LutView::~LutView(){ 54 | delete background; 55 | delete _scene; 56 | } 57 | void LutView::dragEnterEvent(QDragEnterEvent *event){ 58 | _scene->setSceneRect(rect()); 59 | LutCursor::setDim(width(),height()); 60 | background->width=width(); 61 | background->height=height(); 62 | if(event->mimeData()->hasColor()){ 63 | event->setAccepted(true); 64 | curs= new LutCursor(event->mimeData()->colorData().value()); 65 | curs->c=grd.add(event->mimeData()->colorData().value().rgb(),event->posF().x()/width()); 66 | curs->setPos(event->pos().x(),height()/2); 67 | _scene->addItem(curs); 68 | } 69 | background->update(); 70 | } 71 | void LutView::dragMoveEvent(QDragMoveEvent *event){ 72 | curs->setPos(event->pos().x(),height()/2); 73 | background->update(); 74 | } 75 | void LutView::dragLeaveEvent(QDragLeaveEvent *){ 76 | _scene->removeItem(curs); 77 | grd.remove(curs->c); 78 | delete curs; 79 | background->update(); 80 | } 81 | 82 | int LutCursor::height; 83 | int LutCursor::width; 84 | LutCursor::LutCursor(const QColor& color):color(color){ 85 | setFlag(ItemSendsGeometryChanges); 86 | } 87 | void LutCursor::setDim(int w, int h){ 88 | width=w; 89 | height=h; 90 | } 91 | QRectF LutCursor::boundingRect()const{ 92 | return QRect(-cursorRadius, -height/2, 2*cursorRadius, height); 93 | } 94 | void LutCursor::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *){ 95 | p->drawLine(0,-height/2,0,height/2); 96 | p->setBrush(color); 97 | p->drawEllipse({0,0},cursorRadius,cursorRadius); 98 | } 99 | 100 | QVariant LutCursor::itemChange(GraphicsItemChange change, const QVariant &v){ 101 | if(change==ItemPositionChange&&x()){ 102 | QPointF p= v.toPointF(); 103 | p.setY(height/2); 104 | c->updateAlpha(x()/width); 105 | return p; 106 | } 107 | return QGraphicsItem::itemChange(change, v); 108 | } 109 | 110 | void LutCursor::mouseReleaseEvent(QGraphicsSceneMouseEvent*){ 111 | setCursor(Qt::ArrowCursor); 112 | if(scenePos().x()<0 || scenePos().x()>scene()->width()){ 113 | scene()->removeItem(this); 114 | c->gr->remove(c); 115 | delete this; 116 | } 117 | } 118 | void LutCursor::mouseMoveEvent(QGraphicsSceneMouseEvent*event){ 119 | setCursor(Qt::SizeHorCursor); 120 | setPos(event->scenePos()); 121 | QGraphicsItem::mouseMoveEvent(event); 122 | } 123 | 124 | LutBackground::LutBackground(Gradient *g):grd(g){ 125 | setZValue(INT_MIN); 126 | } 127 | void LutBackground::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *){ 128 | if(!grd->empty()) 129 | for(int x=0;xsetPen(QColor::fromRgb((*grd)[(double)x/width])); 131 | p->drawLine(x,0,x,height); 132 | } 133 | scene()->update(); 134 | } 135 | QRectF LutBackground::boundingRect()const{ 136 | return QRectF(0,0,width,height); 137 | } 138 | -------------------------------------------------------------------------------- /plugins/lut/dialog/lut_dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef LUT_DIALOG_H 2 | #define LUT_DIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "../Gradient.h" 8 | 9 | class LutBackground:public QGraphicsItem{ 10 | public: 11 | LutBackground(Gradient*); 12 | int width,height; 13 | private: 14 | const Gradient*grd; 15 | void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); 16 | QRectF boundingRect()const; 17 | }; 18 | 19 | class LutCursor:public QGraphicsItem{ 20 | public: 21 | LutCursor(const QColor &color); 22 | static void setDim(int w, int h); 23 | private: 24 | static int height; 25 | static int width; 26 | const QColor color; 27 | Gradient::color* c; 28 | QRectF boundingRect()const; 29 | static const int cursorRadius=5; 30 | QVariant itemChange(GraphicsItemChange, const QVariant &); 31 | void paint(QPainter*,const QStyleOptionGraphicsItem*,QWidget*); 32 | void mousePressEvent(QGraphicsSceneMouseEvent*){} 33 | void mouseReleaseEvent(QGraphicsSceneMouseEvent*); 34 | void mouseMoveEvent(QGraphicsSceneMouseEvent *); 35 | friend class LutView; 36 | }; 37 | 38 | class LutView:public QGraphicsView{ 39 | public: 40 | LutView(QWidget* parent=0); 41 | ~LutView(); 42 | private: 43 | QGraphicsScene* _scene; 44 | static LutCursor* curs; 45 | Gradient grd; 46 | LutBackground* background; 47 | void dragEnterEvent(QDragEnterEvent*); 48 | void dragLeaveEvent(QDragLeaveEvent*); 49 | void dragMoveEvent(QDragMoveEvent*); 50 | friend class LutDialog; 51 | }; 52 | 53 | class LutDialog : public QDialog{ 54 | Q_OBJECT 55 | public: 56 | explicit LutDialog(QWidget *parent = 0); 57 | static Gradient *getGradient(); 58 | private: 59 | LutView* view; 60 | ~LutDialog(); 61 | }; 62 | 63 | #endif // LUT_DIALOG_H 64 | -------------------------------------------------------------------------------- /plugins/lut/fromToStream.cpp: -------------------------------------------------------------------------------- 1 | #include "LUTNode.h" 2 | #include "dialog/lut_dialog.h" 3 | 4 | void Gradient::toBin(std::ostream& out)const{ 5 | uint n=0; 6 | for(auto it=first; it;it=it->next) 7 | n++; 8 | out.write(reinterpret_cast(&n),sizeof(uint)); 9 | for(auto it= first; it; it=it->next){ 10 | out.write(reinterpret_cast(&it->clr),sizeof(uint)); 11 | out.write(reinterpret_cast(&it->alpha),sizeof(double)); 12 | } 13 | } 14 | void Gradient::toText(std::ostream& out)const{ 15 | uint n=0; 16 | for(auto it=first; it;it=it->next) 17 | n++; 18 | out << n <<' '; 19 | for(auto it= first; it; it=it->next){ 20 | out << it->clr <<' '<< it->alpha; 21 | if(it->next) out<<' '; 22 | } 23 | } 24 | 25 | Node* LUTNode::makeFromBin(std::istream&in){ 26 | Gradient *g; 27 | if(in.peek()!=EOF){ 28 | g= new Gradient; 29 | uint n; 30 | in.read(reinterpret_cast(&n),sizeof(uint)); 31 | double alpha; 32 | data_t::color color; 33 | for(uint i=0;i(&color),sizeof(data_t::color)); 35 | in.read(reinterpret_cast(&alpha),sizeof(double)); 36 | g->add(color,alpha); 37 | } 38 | } 39 | else g= LutDialog::getGradient(); 40 | if(g)return new LUTNode(g); 41 | return nullptr; 42 | } 43 | Node* LUTNode::makeFromText(std::istream&in){ 44 | Gradient *g; 45 | if(in.peek()!=EOF){ 46 | g= new Gradient; 47 | uint n; 48 | in>>n; 49 | double alpha; 50 | data_t::color color; 51 | for(uint i=0;i> color; 53 | in >> alpha; 54 | g->add(color,alpha); 55 | } 56 | } 57 | else g= LutDialog::getGradient(); 58 | if(g)return new LUTNode(g); 59 | return nullptr; 60 | } 61 | 62 | void LUTNode::toBin(std::ostream &out)const{ 63 | Node::toBin(out); 64 | gradient.toBin(out); 65 | } 66 | void LUTNode::toText(std::ostream &out)const{ 67 | Node::toText(out); 68 | out<< ' '; 69 | gradient.toText(out); 70 | } 71 | -------------------------------------------------------------------------------- /plugins/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(MathPlugin) 3 | 4 | find_package(Qt5Widgets REQUIRED) 5 | 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 9 | qt5_add_resources(QRC math.qrc) 10 | add_custom_target(math_qrc DEPENDS ${QRC}) 11 | 12 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PLUGIN_OUTPUT_PATH}) 13 | 14 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 15 | 16 | add_library(${PROJECT_NAME} SHARED MathPlugin.cpp MathPlugin.h) 17 | add_library(math 18 | MathNode.cpp 19 | RealNode.cpp 20 | ComplexNode.cpp 21 | MathNode.h 22 | RealNode.h 23 | fromToStream.cpp 24 | ComplexNode.h) 25 | 26 | target_link_libraries(${PROJECT_NAME} math data_t ${QRC}) 27 | add_dependencies(${PROJECT_NAME} math_qrc) 28 | -------------------------------------------------------------------------------- /plugins/math/ComplexNode.cpp: -------------------------------------------------------------------------------- 1 | #include "ComplexNode.h" 2 | 3 | ComplexNode::ComplexNode():Node("cplx",50,50,Qt::white,2){} 4 | 5 | void ComplexNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 6 | Node::paint(painter,option,widget); 7 | drawIcon(painter,":/complex.png"); 8 | } 9 | 10 | data_t ComplexNode::kernel()const{ 11 | return cplx(iNodes[0]->eval(),iNodes[1]->eval()); 12 | } 13 | -------------------------------------------------------------------------------- /plugins/math/ComplexNode.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPLEXNODE_H 2 | #define COMPLEXNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class ComplexNode : public Node{ 7 | public: 8 | ComplexNode(); 9 | inline static Node* makeNode(std::istream&){return new ComplexNode;} 10 | private: 11 | data_t kernel()const; 12 | void paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*); 13 | }; 14 | 15 | #endif // COMPLEXNODE_H 16 | -------------------------------------------------------------------------------- /plugins/math/MathNode.cpp: -------------------------------------------------------------------------------- 1 | #include "MathNode.h" 2 | 3 | #include 4 | #include 5 | 6 | MathNode::MathNode(const std::string &type, unsigned n, unsigned w, unsigned h):Node(type,w,h,QColor(180,255,180),n){} 7 | 8 | ADDNode::ADDNode():MathNode("add",2){} 9 | SUBNode::SUBNode():MathNode("sub",2){} 10 | MULNode::MULNode():MathNode("mul",2){} 11 | DIVNode::DIVNode():MathNode("div",2){} 12 | NEGNode::NEGNode():MathNode("neg",1){} 13 | SQRTNode::SQRTNode():MathNode("sqrt",1){} 14 | ABSNode::ABSNode():MathNode("abs",1){} 15 | LERPNode::LERPNode():MathNode("lerp",3,50,100){} 16 | CLAMPNode::CLAMPNode():MathNode("clamp",3,50,100){} 17 | SINNode::SINNode():MathNode("sin",1){} 18 | COSNode::COSNode():MathNode("cos",1){} 19 | MINNode::MINNode():MathNode("min",2){} 20 | MAXNode::MAXNode():MathNode("max",2){} 21 | POWNode::POWNode():MathNode("pow",2){} 22 | LOGNode::LOGNode():MathNode("log",1){} 23 | 24 | void ADDNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 25 | Node::paint(painter,option,widget); 26 | drawIcon(painter,":/add.png"); 27 | } 28 | 29 | void SUBNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 30 | Node::paint(painter,option,widget); 31 | drawIcon(painter,":/subtract.png"); 32 | } 33 | 34 | void MULNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 35 | Node::paint(painter,option,widget); 36 | drawIcon(painter,":/multiply.png"); 37 | } 38 | 39 | void DIVNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 40 | Node::paint(painter,option,widget); 41 | drawIcon(painter,":/divide.png"); 42 | } 43 | 44 | void NEGNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 45 | Node::paint(painter,option,widget); 46 | drawIcon(painter,":/neg.png"); 47 | } 48 | 49 | void SQRTNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 50 | Node::paint(painter,option,widget); 51 | QImage icon=QImage(":/sqrt.png"); 52 | painter->drawImage(width/2-icon.width()/2+5,height/2-icon.height()/2,icon); 53 | } 54 | void ABSNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 55 | Node::paint(painter,option,widget); 56 | painter->drawText(boundingRect().center()-QPointF(12,0),"abs"); 57 | } 58 | void LERPNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 59 | Node::paint(painter,option,widget); 60 | QRectF rect=boundingRect(); 61 | painter->drawText(rect.topLeft()+QPointF(8,rect.height()/4.0+4),"1"); 62 | painter->drawText(rect.topLeft()+QPointF(width/2,2*rect.height()/4.0+4),"lerp"); 63 | painter->drawText(rect.topLeft()+QPointF(8,3*rect.height()/4.0+4),"0"); 64 | } 65 | void CLAMPNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 66 | Node::paint(painter,option,widget); 67 | QRectF rect=boundingRect(); 68 | painter->drawText(rect.topLeft()+QPointF(8,rect.height()/4.0+4),"1"); 69 | painter->drawText(rect.topLeft()+QPointF(width/2-10,2*rect.height()/4.0+4),"clamp"); 70 | painter->drawText(rect.topLeft()+QPointF(8,3*rect.height()/4.0+4),"0"); 71 | } 72 | void SINNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 73 | Node::paint(painter,option,widget); 74 | painter->drawText(boundingRect().center()-QPointF(12,0),"sin"); 75 | } 76 | void COSNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 77 | Node::paint(painter,option,widget); 78 | painter->drawText(boundingRect().center()-QPointF(12,0),"cos"); 79 | } 80 | void MINNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 81 | Node::paint(painter,option,widget); 82 | painter->drawText(boundingRect().center()-QPointF(12,0),"min"); 83 | } 84 | void MAXNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 85 | Node::paint(painter,option,widget); 86 | painter->drawText(boundingRect().center()-QPointF(12,0),"max"); 87 | } 88 | void POWNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 89 | Node::paint(painter,option,widget); 90 | painter->drawText(boundingRect().center()-QPointF(12,0),"pow"); 91 | } 92 | void LOGNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ 93 | Node::paint(painter,option,widget); 94 | painter->drawText(boundingRect().center()-QPointF(12,0),"log"); 95 | } 96 | data_t ADDNode::kernel()const{ 97 | return iNodes[0]->eval()+iNodes[1]->eval(); 98 | } 99 | data_t SUBNode::kernel()const{ 100 | return iNodes[0]->eval()-iNodes[1]->eval(); 101 | } 102 | data_t MULNode::kernel()const{ 103 | return iNodes[0]->eval()*iNodes[1]->eval(); 104 | } 105 | data_t DIVNode::kernel()const{ 106 | return iNodes[0]->eval()/iNodes[1]->eval(); 107 | } 108 | data_t NEGNode::kernel()const{ 109 | return -iNodes[0]->eval(); 110 | } 111 | data_t SQRTNode::kernel()const{ 112 | return iNodes[0]->eval().sqrt(); 113 | } 114 | data_t ABSNode::kernel()const{ 115 | return qAbs((double)iNodes[0]->eval()); 116 | } 117 | data_t LERPNode::kernel()const{ 118 | double alpha=iNodes[1]->eval(); 119 | return (1.0-alpha)*double(iNodes[2]->eval())+alpha*double(iNodes[0]->eval()); 120 | } 121 | data_t CLAMPNode::kernel()const{ 122 | double min=iNodes[2]->eval(), max=iNodes[0]->eval(); 123 | if(!(max-min)) return 0.0; 124 | return (double(iNodes[1]->eval())-min)/(max-min); 125 | } 126 | data_t SINNode::kernel()const{ 127 | return iNodes[0]->eval().sin(); 128 | } 129 | data_t COSNode::kernel()const{ 130 | return iNodes[0]->eval().cos(); 131 | } 132 | data_t MINNode::kernel()const{ 133 | return qMin(iNodes[0]->eval(),iNodes[1]->eval()); 134 | } 135 | data_t MAXNode::kernel()const{ 136 | return qMax(iNodes[0]->eval(),iNodes[1]->eval()); 137 | } 138 | data_t POWNode::kernel()const{ 139 | return pow(iNodes[0]->eval(),iNodes[1]->eval()); 140 | } 141 | data_t LOGNode::kernel()const{ 142 | return iNodes[0]->eval().log(); 143 | } 144 | -------------------------------------------------------------------------------- /plugins/math/MathNode.h: -------------------------------------------------------------------------------- 1 | #ifndef MATHNODE_H 2 | #define MATHNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class MathNode:public Node{ 7 | protected: 8 | MathNode(const std::string &type, unsigned n, unsigned w=50, unsigned h=50); 9 | virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)=0; 10 | }; 11 | 12 | class ADDNode:public MathNode{ 13 | public: 14 | ADDNode(); 15 | inline static Node* makeNode(std::istream&){return new ADDNode;} 16 | private: 17 | data_t kernel()const; 18 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 19 | }; 20 | 21 | class SUBNode:public MathNode{ 22 | public: 23 | SUBNode(); 24 | inline static Node* makeNode(std::istream&){return new SUBNode;} 25 | private: 26 | data_t kernel()const; 27 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 28 | }; 29 | 30 | class MULNode:public MathNode{ 31 | public: 32 | MULNode(); 33 | inline static Node* makeNode(std::istream&){return new MULNode;} 34 | private: 35 | data_t kernel()const; 36 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 37 | }; 38 | 39 | class DIVNode:public MathNode{ 40 | public: 41 | DIVNode(); 42 | inline static Node* makeNode(std::istream&){return new DIVNode;} 43 | private: 44 | data_t kernel()const; 45 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 46 | }; 47 | 48 | class NEGNode:public MathNode{ 49 | public: 50 | NEGNode(); 51 | inline static Node* makeNode(std::istream&){return new NEGNode;} 52 | private: 53 | data_t kernel()const; 54 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 55 | }; 56 | 57 | class SQRTNode:public MathNode{ 58 | public: 59 | SQRTNode(); 60 | inline static Node* makeNode(std::istream&){return new SQRTNode;} 61 | private: 62 | data_t kernel()const; 63 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 64 | }; 65 | 66 | class ABSNode:public MathNode{ 67 | public: 68 | ABSNode(); 69 | inline static Node* makeNode(std::istream&){return new ABSNode;} 70 | private: 71 | data_t kernel()const; 72 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 73 | }; 74 | class LERPNode:public MathNode{ 75 | public: 76 | LERPNode(); 77 | inline static Node* makeNode(std::istream&){return new LERPNode;} 78 | private: 79 | data_t kernel()const; 80 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 81 | }; 82 | class CLAMPNode:public MathNode{ 83 | public: 84 | CLAMPNode(); 85 | inline static Node* makeNode(std::istream&){return new CLAMPNode;} 86 | private: 87 | data_t kernel()const; 88 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 89 | }; 90 | class SINNode:public MathNode{ 91 | public: 92 | SINNode(); 93 | inline static Node* makeNode(std::istream&){return new SINNode;} 94 | private: 95 | data_t kernel()const; 96 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 97 | }; 98 | class COSNode:public MathNode{ 99 | public: 100 | COSNode(); 101 | inline static Node* makeNode(std::istream&){return new COSNode;} 102 | private: 103 | data_t kernel()const; 104 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 105 | }; 106 | 107 | class MINNode:public MathNode{ 108 | public: 109 | MINNode(); 110 | inline static Node* makeNode(std::istream&){return new MINNode;} 111 | private: 112 | data_t kernel()const; 113 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 114 | }; 115 | class MAXNode:public MathNode{ 116 | public: 117 | MAXNode(); 118 | inline static Node* makeNode(std::istream&){return new MAXNode;} 119 | private: 120 | data_t kernel()const; 121 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 122 | }; 123 | class POWNode:public MathNode{ 124 | public: 125 | POWNode(); 126 | inline static Node* makeNode(std::istream&){return new POWNode;} 127 | private: 128 | data_t kernel()const; 129 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 130 | }; 131 | class LOGNode:public MathNode{ 132 | public: 133 | LOGNode(); 134 | inline static Node* makeNode(std::istream&){return new LOGNode;} 135 | private: 136 | data_t kernel()const; 137 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); 138 | }; 139 | #endif // MATHNODE_H 140 | -------------------------------------------------------------------------------- /plugins/math/MathPlugin.cpp: -------------------------------------------------------------------------------- 1 | #include "MathPlugin.h" 2 | #include "MathNode.h" 3 | #include "RealNode.h" 4 | #include "ComplexNode.h" 5 | 6 | void MathPlugin::updateUI(Ui::MainWindow* ui) const{ 7 | QMenu* mathMenu = new QMenu("Math",ui->menuInsert); 8 | ui->menuInsert->addAction(mathMenu->menuAction()); 9 | QAction* addAction= new QAction(QIcon(":/add.png"),"Add"); 10 | QAction* subAction= new QAction(QIcon(":/subtract.png"),"Subtract"); 11 | QAction* mulAction= new QAction(QIcon(":/multiply.png"),"Multiply"); 12 | QAction* divAction= new QAction(QIcon(":/divide.png"),"Divide"); 13 | QAction* realAction= new QAction(QIcon(":/real.png"),"Real"); 14 | QAction* complexAction= new QAction(QIcon(":/complex.png"),"Complex"); 15 | QAction* sqrtAction= new QAction(QIcon(":/sqrt.png"),"Square Root"); 16 | QAction* absAction= new QAction("Absolute Value"); 17 | QAction* negAction= new QAction(QIcon(":/neg.png"),"Neg"); 18 | QAction* minAction= new QAction("Min"); 19 | QAction* maxAction= new QAction("Max"); 20 | QAction* powAction= new QAction("Power"); 21 | QAction* logAction= new QAction("Logarithm"); 22 | QAction* sinAction= new QAction(QIcon(":/sin.png"),"Sin"); 23 | QAction* cosAction= new QAction(QIcon(":/cos.png"),"Cos"); 24 | QAction* lerpAction= new QAction("Linear Interpolation"); 25 | QAction* clampAction= new QAction("Clamp"); 26 | 27 | Workspace* ws=(Workspace*)ui->workspace->scene(); 28 | connect(addAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("add"));}); 29 | connect(subAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("sub"));}); 30 | connect(mulAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("mul"));}); 31 | connect(divAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("div"));}); 32 | connect(realAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("real"));}); 33 | connect(complexAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("cplx"));}); 34 | connect(sqrtAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("sqrt"));}); 35 | connect(absAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("abs"));}); 36 | connect(negAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("neg"));}); 37 | connect(minAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("min"));}); 38 | connect(maxAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("max"));}); 39 | connect(powAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("pow"));}); 40 | connect(logAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("log"));}); 41 | connect(sinAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("sin"));}); 42 | connect(cosAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("cos"));}); 43 | connect(lerpAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("lerp"));}); 44 | connect(clampAction,&QAction::triggered,ws,[=]{ws->addNode(Node::nodeMalloc("clamp"));}); 45 | 46 | mathMenu->addAction(addAction); 47 | mathMenu->addAction(subAction); 48 | mathMenu->addAction(mulAction); 49 | mathMenu->addAction(divAction); 50 | mathMenu->addAction(realAction); 51 | mathMenu->addAction(complexAction); 52 | mathMenu->addAction(sqrtAction); 53 | mathMenu->addAction(absAction); 54 | mathMenu->addAction(negAction); 55 | mathMenu->addAction(minAction); 56 | mathMenu->addAction(maxAction); 57 | mathMenu->addAction(powAction); 58 | mathMenu->addAction(logAction); 59 | mathMenu->addAction(sinAction); 60 | mathMenu->addAction(cosAction); 61 | mathMenu->addAction(lerpAction); 62 | mathMenu->addAction(clampAction); 63 | } 64 | 65 | void MathPlugin::init()const{ 66 | Node::makeNodeBinTextMethods["add"] = {&ADDNode::makeNode,&ADDNode::makeNode}; 67 | Node::makeNodeBinTextMethods["sub"] = {&SUBNode::makeNode,&SUBNode::makeNode}; 68 | Node::makeNodeBinTextMethods["mul"] = {&MULNode::makeNode,&MULNode::makeNode}; 69 | Node::makeNodeBinTextMethods["div"] = {&DIVNode::makeNode,&DIVNode::makeNode}; 70 | Node::makeNodeBinTextMethods["real"] = {&RealNode::makeFromBin,&RealNode::makeFromText}; 71 | Node::makeNodeBinTextMethods["cplx"] = {&ComplexNode::makeNode,&ComplexNode::makeNode}; 72 | Node::makeNodeBinTextMethods["sqrt"] = {&SQRTNode::makeNode,&SQRTNode::makeNode}; 73 | Node::makeNodeBinTextMethods["abs"] = {&ABSNode::makeNode,&ABSNode::makeNode}; 74 | Node::makeNodeBinTextMethods["neg"] = {&NEGNode::makeNode,&NEGNode::makeNode}; 75 | Node::makeNodeBinTextMethods["min"] = {&MINNode::makeNode,&MINNode::makeNode}; 76 | Node::makeNodeBinTextMethods["max"] = {&MAXNode::makeNode,&MAXNode::makeNode}; 77 | Node::makeNodeBinTextMethods["pow"] = {&POWNode::makeNode,&POWNode::makeNode}; 78 | Node::makeNodeBinTextMethods["log"] = {&LOGNode::makeNode,&LOGNode::makeNode}; 79 | Node::makeNodeBinTextMethods["sin"] = {&SINNode::makeNode,&SINNode::makeNode}; 80 | Node::makeNodeBinTextMethods["cos"] = {&COSNode::makeNode,&COSNode::makeNode}; 81 | Node::makeNodeBinTextMethods["lerp"] = {&LERPNode::makeNode,&LERPNode::makeNode}; 82 | Node::makeNodeBinTextMethods["clamp"]= {&CLAMPNode::makeNode,&CLAMPNode::makeNode}; 83 | 84 | NodeBox::addTool("add","Add",QIcon(":/add.png"),"Math"); 85 | NodeBox::addTool("sub","Subtract",QIcon(":/subtract.png"),"Math"); 86 | NodeBox::addTool("mul","Multiply",QIcon(":/multiply.png"),"Math"); 87 | NodeBox::addTool("div","Divide",QIcon(":/divide.png"),"Math"); 88 | NodeBox::addTool("real","Real",QIcon(":/real.png"),"Math"); 89 | NodeBox::addTool("cplx","Complex",QIcon(":/complex.png"),"Math"); 90 | NodeBox::addTool("sqrt","Square Root",QIcon(":/sqrt.png"),"Math"); 91 | NodeBox::addTool("abs","Absolute Value","Math"); 92 | NodeBox::addTool("neg","Negative",QIcon(":/neg.png"),"Math"); 93 | NodeBox::addTool("min","Min","Math"); 94 | NodeBox::addTool("max","Max","Math"); 95 | NodeBox::addTool("pow","Power","Math"); 96 | NodeBox::addTool("log","Logarithm","Math"); 97 | NodeBox::addTool("sin","Sin",QIcon(":/sin.png"),"Math"); 98 | NodeBox::addTool("cos","Cos",QIcon(":/cos.png"),"Math"); 99 | NodeBox::addTool("lerp","Linear Interpolation","Math"); 100 | NodeBox::addTool("clamp","Clamp","Math"); 101 | } 102 | -------------------------------------------------------------------------------- /plugins/math/MathPlugin.h: -------------------------------------------------------------------------------- 1 | #ifndef MATHPLUGIN_H 2 | #define MATHPLUGIN_H 3 | 4 | #include 5 | #include 6 | 7 | #include "EmergenceInterface.h" 8 | 9 | class MathPlugin: public QObject, EmergenceInterface{ 10 | Q_OBJECT 11 | Q_PLUGIN_METADATA(IID "Emergence.Node.Plugin") 12 | Q_INTERFACES(EmergenceInterface) 13 | public: 14 | void updateUI(Ui::MainWindow*)const override; 15 | void init()const override; 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/math/RealNode.cpp: -------------------------------------------------------------------------------- 1 | #include "RealNode.h" 2 | 3 | #include 4 | #include 5 | 6 | RealNode::RealNode(double v):Node("real",50,50,QColor(255,255,180)){ 7 | cache=v; 8 | constant=true; 9 | } 10 | 11 | void RealNode::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*widget){ 12 | Node::paint(painter,option,widget); 13 | painter->drawText(boundingRect().center()-QPoint(12,-2),QString::number(cache.d)); 14 | } 15 | 16 | void RealNode::contextMenuEvent(QGraphicsSceneContextMenuEvent* event){ 17 | menu=new QMenu; 18 | connect(menu->addAction(QString("Change number")), &QAction::triggered,this,&RealNode::changeNumber); 19 | Node::contextMenuEvent(event); 20 | } 21 | 22 | void RealNode::mouseDoubleClickEvent(QGraphicsSceneMouseEvent*){ 23 | changeNumber(); 24 | } 25 | 26 | void RealNode::changeNumber(){ 27 | bool ok; 28 | double d =QInputDialog::getDouble((QWidget*)parentWidget(),"Choose Number","",0,-2147483647,2147483647,3,&ok); 29 | if(ok){ 30 | cache=d; 31 | updateVal(); 32 | emit sm.updateOutputs(); 33 | update(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /plugins/math/RealNode.h: -------------------------------------------------------------------------------- 1 | #ifndef REALNODE_H 2 | #define REALNODE_H 3 | 4 | #include "Node.h" 5 | 6 | class RealNode:public Node{ 7 | public: 8 | RealNode(double v=0); 9 | static Node* makeFromBin(std::istream&); 10 | static Node* makeFromText(std::istream&); 11 | private: 12 | inline data_t kernel()const{return cache;} 13 | virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget*widget); 14 | void contextMenuEvent(QGraphicsSceneContextMenuEvent* event); 15 | void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*); 16 | void toBin(std::ostream &)const override; 17 | void toText(std::ostream &)const override; 18 | private slots: 19 | void changeNumber(); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /plugins/math/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/add.png -------------------------------------------------------------------------------- /plugins/math/complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/complex.png -------------------------------------------------------------------------------- /plugins/math/cos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/cos.png -------------------------------------------------------------------------------- /plugins/math/divide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/divide.png -------------------------------------------------------------------------------- /plugins/math/fromToStream.cpp: -------------------------------------------------------------------------------- 1 | #include "RealNode.h" 2 | 3 | Node* RealNode::makeFromBin(std::istream &in){ 4 | if(in.peek()!=EOF){ 5 | double d; 6 | in.read(reinterpret_cast(&d) ,sizeof(double)); 7 | return new RealNode(d); 8 | } 9 | return new RealNode; 10 | } 11 | Node* RealNode::makeFromText(std::istream &in){ 12 | if(in.peek()!=EOF){ 13 | double d; 14 | in>>d; 15 | return new RealNode(d); 16 | } 17 | return new RealNode; 18 | } 19 | 20 | void RealNode::toBin(std::ostream &out) const{ 21 | Node::toBin(out); 22 | out.write(reinterpret_cast(&cache.d),sizeof(double)); 23 | } 24 | void RealNode::toText(std::ostream &out) const{ 25 | Node::toText(out); 26 | out <<' '<< cache.d; 27 | } 28 | -------------------------------------------------------------------------------- /plugins/math/math.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | add.png 4 | complex.png 5 | cos.png 6 | divide.png 7 | multiply.png 8 | neg.png 9 | real.png 10 | sqrt.png 11 | sin.png 12 | subtract.png 13 | 14 | 15 | -------------------------------------------------------------------------------- /plugins/math/multiply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/multiply.png -------------------------------------------------------------------------------- /plugins/math/neg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/neg.png -------------------------------------------------------------------------------- /plugins/math/real.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/real.png -------------------------------------------------------------------------------- /plugins/math/sin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/sin.png -------------------------------------------------------------------------------- /plugins/math/sqrt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/sqrt.png -------------------------------------------------------------------------------- /plugins/math/subtract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/plugins/math/subtract.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | 3 | find_package(Qt5Widgets REQUIRED) 4 | 5 | set(CMAKE_AUTOUIC ON) 6 | set(CMAKE_AUTOMOC ON) 7 | set(CMAKE_AUTORCC ON) 8 | 9 | file(GLOB FORMS *.ui) 10 | qt5_wrap_ui(UI_HEADERS ${FORMS}) 11 | qt5_add_resources(QRC src.qrc) 12 | 13 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") 14 | 15 | include_directories(${MAIN_SRC_DIR} ${BIN_SRC_DIR} ${Qt5Widgets_INCLUDE_DIRS}) 16 | 17 | add_library(data_t data_t.cpp data_t.h) 18 | 19 | add_library(core 20 | mainwindow.cpp 21 | Node.cpp 22 | NodeBox.cpp 23 | Workspace.cpp 24 | PluginManager.cpp 25 | mainwindow.h 26 | Node.h 27 | NodeBox.h 28 | Workspace.h 29 | PluginManager.h 30 | signalManager.h 31 | ${UI_HEADERS}) 32 | 33 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ..) 34 | add_executable(${PROJECT_NAME} main.cpp ${QRC}) 35 | 36 | target_link_libraries(${PROJECT_NAME} data_t core Qt5::Widgets) 37 | -------------------------------------------------------------------------------- /src/EmergenceInterface.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Workspace.h" 6 | #include "ui_mainwindow.h" 7 | 8 | class EmergenceInterface{ 9 | public: 10 | virtual void updateUI(Ui::MainWindow*)const{} 11 | virtual void init()const{} 12 | inline virtual bool redefineSaveLoad()const{return false;} 13 | virtual void toBin(std::ostream&)const{} 14 | virtual void toText(std::ostream&)const{} 15 | virtual void fromBin(std::istream&)const{} 16 | virtual void fromText(std::istream&)const{} 17 | }; 18 | 19 | Q_DECLARE_INTERFACE(EmergenceInterface, "Emergence.Node.Plugin") 20 | -------------------------------------------------------------------------------- /src/Node.cpp: -------------------------------------------------------------------------------- 1 | #include "Node.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | Node::Socket::Socket(unsigned i, double y, Node *parent):QGraphicsObject(parent) 8 | ,line(headSize,0,headSize,0),rank(i),iy(y),parent(parent){ 9 | setZValue(parent->zValue()+1); 10 | setPos(-headSize-1,y); 11 | setAcceptHoverEvents(true); 12 | line.setParentItem(this); 13 | connect(this,&Node::Socket::xChanged,this,&Node::Socket::updateLine); 14 | connect(this,&Node::Socket::yChanged,this,&Node::Socket::updateLine); 15 | } 16 | 17 | Node::Socket::~Socket(){ 18 | disconnect(this,&Node::Socket::yChanged,this,&Node::Socket::updateLine); 19 | disconnect(this,&Node::Socket::xChanged,this,&Node::Socket::updateLine); 20 | } 21 | 22 | QRectF Node::Socket::boundingRect()const{ 23 | return QRectF(-headSize,-headSize,headSize*2+1,headSize*2+1); 24 | } 25 | 26 | void Node::Socket::updateLine(){ 27 | line.setLine(QLine({headSize,0},(parentItem()->pos()-scenePos()-QPointF(0,-iy)).toPoint())); 28 | } 29 | 30 | void Node::Socket::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *){ 31 | if(visible){ 32 | painter->setPen(pen); 33 | painter->setRenderHint(QPainter::Antialiasing); 34 | painter->drawEllipse(boundingRect().center(),headSize,headSize); 35 | } 36 | } 37 | 38 | void Node::Socket::hoverEnterEvent(QGraphicsSceneHoverEvent *){ 39 | pen.setWidth(2); 40 | update(); 41 | } 42 | 43 | void Node::Socket::hoverLeaveEvent(QGraphicsSceneHoverEvent *){ 44 | pen.setWidth(1); 45 | update(); 46 | } 47 | 48 | Node* Node::Socket::collidesWithNode() const{ 49 | for(auto& i:collidingItems()) 50 | if(i->data(0)=="node") 51 | return (Node*)i; 52 | return nullptr; 53 | } 54 | 55 | void Node::Socket::mouseMoveEvent(QGraphicsSceneMouseEvent*event){ 56 | Node*i=collidesWithNode(); 57 | if(i&&!i->isLooping(parent)&&i->contains(event->scenePos()-i->scenePos())){ 58 | hover=i; 59 | for(const auto& ii: i->collidingItems()) 60 | if(i->zValue()<= ii->zValue()) 61 | i->setZValue(ii->zValue()+1); 62 | parent->setZValue(i->zValue()); 63 | setZValue(i->zValue()); 64 | setPos(i->pos()+QPoint(i->boundingRect().width()+Socket::headSize-1,i->height/2)-parent->pos()); 65 | }else{ 66 | hover=nullptr; 67 | setPos(event->scenePos()- boundingRect().center()-parent->pos()); 68 | } 69 | } 70 | 71 | void Node::Socket::connectToNode(Node* n){ 72 | if(n==parent) return; 73 | if(parent->nbArgs>=rank+1 && !parent->iNodes[rank]){ 74 | QRectF r= n->boundingRect(); 75 | setPos(n->pos()+QPoint(r.width()-Socket::headSize,r.height()/2)-parent->pos()); 76 | parent->iNodes[rank]=n; 77 | n->oConnections.push_back({parent,rank}); 78 | connect(n,&Node::xChanged,this,&Node::Socket::updateLine); 79 | connect(n,&Node::yChanged,this,&Node::Socket::updateLine); 80 | setEnabled(false); 81 | visible=false; 82 | parent->updateConstant(); 83 | emit sm.updateOutputs(); 84 | } 85 | } 86 | 87 | void Node::Socket::disconnectNode(){ 88 | if(parent->iNodes[rank]){ 89 | for(auto l=parent->iNodes[rank]->oConnections.begin(); 90 | l!=parent->iNodes[rank]->oConnections.end();++l) 91 | if(l->first==parent && l->second==rank){ 92 | parent->iNodes[rank]->oConnections.erase(l); 93 | break; 94 | } 95 | disconnect(parent->iNodes[rank],&Node::xChanged,this,&Node::Socket::updateLine); 96 | disconnect(parent->iNodes[rank],&Node::yChanged,this,&Node::Socket::updateLine); 97 | parent->iNodes[rank]=nullptr; 98 | reset(); 99 | parent->updateConstant(); 100 | emit sm.updateOutputs(); 101 | } 102 | } 103 | 104 | void Node::Socket::mousePressEvent(QGraphicsSceneMouseEvent*){} 105 | 106 | void Node::Socket::mouseReleaseEvent(QGraphicsSceneMouseEvent*){ 107 | if(hover) emit parent->connected(this,hover); 108 | else reset(); 109 | } 110 | 111 | void Node::Socket::reset(){ 112 | pen.setWidth(1); 113 | visible=true; 114 | setEnabled(true); 115 | setPos(-headSize-1,iy); 116 | line.setLine(headSize,0,headSize,0); 117 | } 118 | 119 | Node* Node::Socket::hover; 120 | SignalManager Node::sm; 121 | 122 | ulong Node::pixelID; 123 | uint Node::widthByHeight; 124 | 125 | Node::Node(const std::string &type, unsigned w, unsigned h, QColor c, uint n, bool spec): 126 | width(w),height(h),_type(type),special(spec),color(c),pen(QPen(Qt::black,1)),nbArgs(n){ 127 | setCursor(Qt::OpenHandCursor); 128 | if(!spec)setData(0,"node"); 129 | setData(1,"countMe"); 130 | for(uint i=0; isetRenderHint(QPainter::Antialiasing); 157 | QPainterPath path; 158 | path.addRoundedRect(rect, 10, 10); 159 | pen.setWidth(isSelected()?2:1); 160 | painter->setPen(pen); 161 | painter->fillPath(path, color); 162 | painter->drawPath(path); 163 | for(uint i=1; i<=nbArgs; i++)//draw input sockets 164 | painter->drawLine(rect.topLeft()+QPointF(0,i*height/(nbArgs+1.0)),rect.topLeft()+QPointF(-socketSize,i*height/(nbArgs+1.0))); 165 | if(!special)//draw output socket 166 | painter->drawLine(rect.center()+QPointF(rect.width()/2,0),rect.center()+QPointF(rect.width()/2+socketSize,0)); 167 | } 168 | 169 | void Node::updateLines()const{ 170 | for(int i = 0; iboundingRect(); 173 | sockets[i]->setPos(iNodes[i]->pos()-pos()+QPointF(r.width()-Socket::headSize,r.height()/2)); 174 | } 175 | for(auto l=oConnections.begin(); l!=oConnections.end();++l) 176 | l->first->sockets[l->second]->setPos(pos()-l->first->pos()+QPointF(boundingRect().width()-Socket::headSize,height/2)); 177 | } 178 | 179 | QPointF Node::tmpPos; 180 | 181 | void Node::mousePressEvent(QGraphicsSceneMouseEvent* event){ 182 | if(event->button()==Qt::LeftButton){ 183 | setCursor(Qt::ClosedHandCursor); 184 | setZValue(INT32_MAX); 185 | }else 186 | setCursor(Qt::ArrowCursor); 187 | tmpPos=pos(); 188 | QGraphicsItem::mousePressEvent(event); 189 | } 190 | void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent*event){ 191 | scene()->setSceneRect(scene()->itemsBoundingRect()); 192 | setCursor(Qt::OpenHandCursor); 193 | setZValue(0); 194 | for(const auto& i: collidingItems()) 195 | if(zValue()<= i->zValue()) 196 | setZValue(i->zValue()+1); 197 | if(pos()-tmpPos!=QPointF(0,0)) 198 | emit moved(); 199 | QGraphicsItem::mouseReleaseEvent(event); 200 | } 201 | 202 | void Node::contextMenuEvent(QGraphicsSceneContextMenuEvent *event){ 203 | if(!menu) menu= new QMenu; 204 | for(unsigned i = 0; iaddAction(QString("Disconnect ")+QString::number(i+1)); 206 | a->setEnabled(iNodes[i]!=nullptr); 207 | connect(a,&QAction::triggered,this,[=](){emit disconnected(sockets[i]);}); 208 | } 209 | menu->addSeparator(); 210 | menu->addAction(actionDelete); 211 | menu->exec(event->screenPos()); 212 | delete menu; 213 | menu=nullptr; 214 | } 215 | 216 | Node::operator bool()const{ 217 | for(auto g:iNodes) 218 | if(g==nullptr || !(*g)) 219 | return false; 220 | return true; 221 | } 222 | 223 | void Node::drawIcon(QPainter *painter, QString filename){ 224 | QImage icon=QImage(filename); 225 | painter->drawImage(width/2-icon.width()/2+socketSize,height/2-icon.height()/2,icon); 226 | } 227 | 228 | void Node::updateVal(){ 229 | if(constant){ 230 | cache=kernel(); 231 | for(const auto& i : oConnections) 232 | i.first->updateVal(); 233 | } 234 | } 235 | 236 | bool Node::isLooping(Node* n)const{ 237 | if(this==n) return true; 238 | for(const auto& node:iNodes) 239 | if(node && node->isLooping(n)) 240 | return true; 241 | return false; 242 | } 243 | void Node::updateConstant(){ 244 | constant=true; 245 | for(const auto& node: iNodes) 246 | if(!node || !node->constant) 247 | constant=false; 248 | if(constant) 249 | cache=kernel(); 250 | for(const auto& i : oConnections) 251 | i.first->updateConstant(); 252 | } 253 | 254 | std::map> Node::makeNodeBinTextMethods; 255 | 256 | Node* Node::nodeMalloc(const std::string& type){ 257 | std::istringstream in; 258 | return nodeMalloc(type,in); 259 | } 260 | Node* Node::nodeMalloc(const std::string& type, std::istream&in){ 261 | if(makeNodeBinTextMethods.find(type)!= makeNodeBinTextMethods.end()) 262 | return makeNodeBinTextMethods[type].first(in); 263 | return nullptr; 264 | } 265 | 266 | data_t Node::eval(){ 267 | if(constant) return cache; 268 | if(pixelID==lastPixelID) return cache; 269 | lastPixelID=pixelID; 270 | return cache=kernel(); 271 | } 272 | 273 | void Node::toBin(std::ostream& out) const{ 274 | out << _type<<'\n'; 275 | int fx,fy; 276 | fx=scenePos().x(); 277 | fy=scenePos().y(); 278 | out.write(reinterpret_cast(&fx),sizeof(int)); 279 | out.write(reinterpret_cast(&fy),sizeof(int)); 280 | } 281 | void Node::toText(std::ostream& out) const{ 282 | out << _type<<' '; 283 | out << scenePos().x()<< ' '; 284 | out << scenePos().y(); 285 | } 286 | //Reads the BINARY data from a stream and creates a list of nodes 287 | std::istream& operator>>(std::istream& in, QList&nodes){ 288 | int tmp; 289 | in.read(reinterpret_cast(&tmp),sizeof(int)); 290 | 291 | std::string type; 292 | int xx,yy; 293 | for(int i=0;i> type; 295 | in.ignore(1); 296 | in.read(reinterpret_cast(&xx),sizeof(int)); 297 | in.read(reinterpret_cast(&yy),sizeof(int)); 298 | Node* n= Node::makeNodeBinTextMethods[type].first(in); 299 | n->setPos(xx,yy); 300 | nodes.push_back(n); 301 | } 302 | for(const auto& n:nodes) 303 | for(uint i=0; inbArgs; i++){ 304 | in.read(reinterpret_cast(&tmp),sizeof(int)); 305 | if(tmp>=0) 306 | n->sockets[i]->connectToNode(nodes.at(tmp)); 307 | } 308 | return in; 309 | } 310 | -------------------------------------------------------------------------------- /src/Node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | #define NODE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "data_t.h" 9 | #include "signalManager.h" 10 | 11 | class Node: public QGraphicsObject{ 12 | Q_OBJECT 13 | public: 14 | Node(const std::string& type, unsigned w=50, unsigned h=50, QColor c=Qt::white, uint n=0, bool spec=false); 15 | ~Node(); 16 | unsigned width, height; 17 | const std::string _type; 18 | virtual data_t eval(); 19 | static Node* nodeMalloc(const std::string &); 20 | static Node* nodeMalloc(const std::string &, std::istream &in); 21 | QVector iNodes; //INPUT NODES 22 | static SignalManager sm; 23 | virtual operator bool()const; 24 | static std::map> makeNodeBinTextMethods; 27 | // friend std::ostream& operator<<(std::ostream& out, const Node&); 28 | // friend std::istream& operator>>(std::istream& in , Node*); 29 | friend std::istream& operator>>(std::istream& in , QList&); 30 | private: 31 | friend class MainWindow; 32 | friend class Workspace; 33 | friend class DeleteNodeCommand; 34 | friend class ConnectNodeCommand; 35 | friend class DisconnectNodeCommand; 36 | friend class MoveNodeCommand; 37 | friend class Function; 38 | bool special; 39 | QPointF initialPos; 40 | static QPointF tmpPos; 41 | void mousePressEvent(QGraphicsSceneMouseEvent *event); 42 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); 43 | virtual data_t kernel()const=0; 44 | bool isLooping(Node *n)const; 45 | void updateConstant(); 46 | protected slots: 47 | void updateLines()const; 48 | void updateVal(); 49 | protected: 50 | struct Socket : public QGraphicsObject{ 51 | Socket(unsigned i, double y, Node *parent); 52 | ~Socket(); 53 | QGraphicsLineItem line; 54 | unsigned rank; 55 | double iy; 56 | static Node *hover; 57 | Node *parent; 58 | bool visible=true; 59 | static const int headSize=8; 60 | QPen pen=QPen(Qt::black); 61 | void connectToNode(Node*n); 62 | void disconnectNode(); 63 | QRectF boundingRect() const; 64 | void updateLine(); 65 | Node* collidesWithNode()const; 66 | void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); 67 | void hoverEnterEvent(QGraphicsSceneHoverEvent*); 68 | void hoverLeaveEvent(QGraphicsSceneHoverEvent*); 69 | void mouseMoveEvent(QGraphicsSceneMouseEvent*); 70 | void mousePressEvent(QGraphicsSceneMouseEvent*); 71 | void mouseReleaseEvent(QGraphicsSceneMouseEvent*); 72 | void reset(); 73 | }; 74 | static const int socketSize=5; 75 | static uint widthByHeight; 76 | static ulong pixelID; 77 | ulong lastPixelID=0; 78 | data_t cache; //value returned by node 79 | bool constant=false; //value is constant 80 | QColor color; 81 | QMenu *menu=nullptr; 82 | QPen pen; 83 | uint nbArgs; 84 | QList> oConnections; 85 | QVector sockets; 86 | QAction* actionDelete; 87 | 88 | QRectF boundingRect()const; 89 | virtual void toBin(std::ostream&)const; 90 | virtual void toText(std::ostream&)const; 91 | virtual void paint(QPainter* painter, 92 | const QStyleOptionGraphicsItem* option, 93 | QWidget* widget); 94 | virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent* event); 95 | void drawIcon(QPainter *painter, QString filename); 96 | signals: 97 | void connected(Node::Socket* s,Node* n); 98 | void disconnected(Node::Socket* s); 99 | void moved(); 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /src/NodeBox.cpp: -------------------------------------------------------------------------------- 1 | #include "NodeBox.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | Workspace* NodeTool::workspace; 12 | QPointF NodeTool::point; 13 | NodeTool::NodeTool(const std::string& id,const QString& text, const QIcon& icon) 14 | :id(id),icon(icon){ 15 | setMinimumHeight(30); 16 | setMaximumHeight(30); 17 | QLabel *lblIcon= new QLabel; 18 | lblIcon->setPixmap(icon.pixmap(24,24)); 19 | QLabel *lbl= new QLabel(text); 20 | QHBoxLayout* hbl= new QHBoxLayout(this); 21 | hbl->setSpacing(1); 22 | hbl->setMargin(0); 23 | hbl->addWidget(lblIcon); 24 | hbl->addWidget(lbl); 25 | hbl->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding)); 26 | lbl->setAttribute(Qt::WA_TransparentForMouseEvents); 27 | setFrameShape(StyledPanel); 28 | setFrameShadow(Raised); 29 | // setAutoFillBackground(true); 30 | // setBackgroundRole(QPalette::Base); 31 | } 32 | 33 | void NodeTool::mouseMoveEvent(QMouseEvent *event){ 34 | QDrag* drag= new QDrag(this); 35 | drag->setPixmap(icon.pixmap(24,24)); 36 | drag->setMimeData(new QMimeData); 37 | workspace=nullptr; 38 | drag->exec(); 39 | if(workspace) 40 | workspace->addNode(Node::nodeMalloc(id),point); 41 | QWidget::mouseMoveEvent(event); 42 | } 43 | 44 | std::vector NodeBox::nodeboxes; 45 | std::vector NodeBox::tools; 46 | NodeBox::NodeBox(QWidget *parent):QToolBox(parent){ 47 | for(const auto& tool:tools) 48 | addTool(tool); 49 | nodeboxes.push_back(this); 50 | } 51 | void NodeBox::addTool(const nodeToolData &tool){ 52 | int i=0; 53 | while(itemText(i)!=tool.category && itemText(i)!="") i++; 54 | QVBoxLayout *vbl; 55 | if(i==count()){ //The Widget-container(page) was not found 56 | QWidget* page = new QWidget; 57 | vbl= new QVBoxLayout(page); 58 | vbl->setSpacing(1); 59 | vbl->setMargin(0); 60 | vbl->addWidget(new NodeTool(tool.id,tool.text,tool.icon)); 61 | vbl->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding)); 62 | addItem(page,tool.category); 63 | }else{ 64 | vbl = (QVBoxLayout*)widget(i)->layout(); 65 | vbl->insertWidget(vbl->count()-1,new NodeTool(tool.id,tool.text,tool.icon)); 66 | } 67 | } 68 | void NodeBox::addTool(const std::string &id, const QString &text, const QString &category){ 69 | addTool(id,text,QIcon(":/no_icon.png"),category); 70 | } 71 | void NodeBox::addTool(const std::string& id, const QString&text, 72 | const QIcon& icon, const QString &category){ 73 | tools.push_back({id,text,icon,category}); 74 | for(auto nb:nodeboxes) 75 | nb->addTool(tools.back()); 76 | } 77 | -------------------------------------------------------------------------------- /src/NodeBox.h: -------------------------------------------------------------------------------- 1 | #ifndef NODEBOX_H 2 | #define NODEBOX_H 3 | 4 | #include 5 | #include "Workspace.h" 6 | 7 | class NodeTool : public QFrame{ 8 | public: 9 | NodeTool(const std::string& id, 10 | const QString &text, 11 | const QIcon&icon); 12 | private: 13 | static Workspace* workspace; 14 | static QPointF point; 15 | std::string id; 16 | QIcon icon; 17 | void mouseMoveEvent(QMouseEvent *event); 18 | friend class Workspace; 19 | }; 20 | 21 | struct nodeToolData{ 22 | const std::string id; 23 | const QString text; 24 | const QIcon icon; 25 | const QString category; 26 | }; 27 | 28 | class NodeBox : public QToolBox{ 29 | public: 30 | NodeBox(QWidget* parent=0); 31 | static void addTool(const std::string &id, 32 | const QString &text, 33 | const QIcon&icon=QIcon(":/no_icon.png"), 34 | const QString &category="Miscellaneous"); 35 | static void addTool(const std::string &id, 36 | const QString &text, 37 | const QString &category); 38 | private: 39 | static std::vector nodeboxes; 40 | static std::vector tools; 41 | void addTool(const nodeToolData&); 42 | }; 43 | 44 | #endif // NODEBOX_H 45 | -------------------------------------------------------------------------------- /src/PluginManager.cpp: -------------------------------------------------------------------------------- 1 | #include "PluginManager.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | PluginManager::PluginManager(Ui::MainWindow *mw):ui(mw){} 8 | 9 | bool PluginManager::loadPlugins(){ 10 | QDir dir(qApp->applicationDirPath()); 11 | dir.cd("lib"); 12 | bool success=false; 13 | for(const auto& fileName: dir.entryList(QDir::Files)){ 14 | QPluginLoader pluginLoader(dir.absoluteFilePath(dir.absoluteFilePath(fileName))); 15 | if (auto plugin = pluginLoader.instance()){ 16 | EmergenceInterface* interface= qobject_cast(plugin); 17 | if (interface){ 18 | interface->init(); 19 | interface->updateUI(ui); 20 | success= true; 21 | if(interface->redefineSaveLoad()) 22 | plugins.push_back(interface); 23 | } 24 | } 25 | } 26 | return success; 27 | } 28 | 29 | void PluginManager::toBin(std::ostream &out)const{ 30 | std::vector usedPlugins; 31 | Workspace* ws = (Workspace*)ui->workspace->scene(); 32 | for(const auto& node: ws->nodes()) 33 | if(std::find(usedPlugins.cbegin(),usedPlugins.cend(),node->_type)==usedPlugins.cend()) 34 | usedPlugins.push_back(node->_type); 35 | int tmp=usedPlugins.size(); 36 | out.write(reinterpret_cast(&tmp),sizeof(int)); 37 | for(const auto& x: usedPlugins){ 38 | out.write(x.data(),sizeof(char)*x.size()); 39 | out<<'\n'; 40 | } 41 | for(const auto& plugin: plugins) 42 | plugin->toBin(out); 43 | } 44 | 45 | void PluginManager::toText(std::ostream &out)const{ 46 | std::vector usedPlugins; 47 | Workspace* ws = (Workspace*)ui->workspace->scene(); 48 | for(const auto& node: ws->nodes()) 49 | if(std::find(usedPlugins.cbegin(),usedPlugins.cend(),node->_type)==usedPlugins.cend()) 50 | usedPlugins.push_back(node->_type); 51 | out << usedPlugins.size() << '\n'; 52 | for(const auto& x: usedPlugins) 53 | out << x << ' '; 54 | out << '\n'; 55 | for(const auto& plugin: plugins) 56 | plugin->toText(out); 57 | } 58 | void PluginManager::fromBin(std::istream &in)const{ 59 | int nbPlugins; 60 | in.read(reinterpret_cast(&nbPlugins),sizeof(int)); 61 | std::vector known; 62 | known.reserve(Node::makeNodeBinTextMethods.size()); 63 | for(const auto& keyValue : Node::makeNodeBinTextMethods) 64 | known.push_back(keyValue.first); 65 | std::string tmp; 66 | for(int i=0; i> tmp; 68 | if(std::find(known.cbegin(),known.cend(),tmp)==known.cend()){ 69 | const std::string message="A plugin containing the implementation of the \""+tmp+"\" node is missing."; 70 | QMessageBox::warning(0,"Missing Plugin",QString::fromStdString(message)); 71 | return; 72 | } 73 | } 74 | in.ignore(1); 75 | for(const auto& plugin: plugins) 76 | plugin->fromBin(in); 77 | } 78 | void PluginManager::fromText(std::istream &in)const{ 79 | int nbPlugins; 80 | in>> nbPlugins; 81 | std::vector known; 82 | known.reserve(Node::makeNodeBinTextMethods.size()); 83 | for(const auto& keyValue : Node::makeNodeBinTextMethods) 84 | known.push_back(keyValue.first); 85 | std::string tmp; 86 | for(int i=0; i> tmp; 88 | if(std::find(known.cbegin(),known.cend(),tmp)==known.cend()){ 89 | const std::string message="A plugin containing the implementation of the \""+tmp+"\" node is missing."; 90 | QMessageBox::warning(0,"Missing Plugin",QString::fromStdString(message)); 91 | return; 92 | } 93 | } 94 | for(const auto& plugin: plugins) 95 | plugin->fromText(in); 96 | } 97 | -------------------------------------------------------------------------------- /src/PluginManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ui_mainwindow.h" 4 | #include "EmergenceInterface.h" 5 | 6 | class PluginManager{ 7 | public: 8 | explicit PluginManager(Ui::MainWindow*); 9 | Ui::MainWindow *ui; 10 | bool loadPlugins(); 11 | void toBin(std::ostream&)const; 12 | void toText(std::ostream&)const; 13 | void fromBin(std::istream&)const; 14 | void fromText(std::istream&)const; 15 | std::vector plugins; 16 | std::vector evalFunctions; 17 | }; 18 | -------------------------------------------------------------------------------- /src/Workspace.cpp: -------------------------------------------------------------------------------- 1 | #include "Workspace.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "NodeBox.h" 9 | 10 | Workspace::Workspace(QWidget *parent):QGraphicsScene(parent){} 11 | 12 | void Workspace::dragEnterEvent(QGraphicsSceneDragDropEvent *event){ 13 | QGraphicsScene::dragEnterEvent(event); 14 | event->accept(); 15 | } 16 | 17 | void Workspace::dropEvent(QGraphicsSceneDragDropEvent *event){ 18 | NodeTool::workspace=this; 19 | NodeTool::point=event->scenePos(); 20 | } 21 | 22 | void Workspace::dragMoveEvent(QGraphicsSceneDragDropEvent*event){ 23 | QGraphicsScene::dragMoveEvent(event); 24 | event->accept(); 25 | } 26 | 27 | void Workspace::addNode(Node* n){ 28 | addNode(n,sceneRect().center()); 29 | } 30 | 31 | void Workspace::addNode(Node *n, const QPointF& pos){ 32 | if(!n) return; 33 | clearSelection(); 34 | n->setPos(pos); 35 | n->initialPos=pos; 36 | connect(n,SIGNAL(moved()),this,SLOT(moveNodes())); 37 | connect(n,SIGNAL(connected(Node::Socket*,Node*)),this,SLOT(connectNode(Node::Socket*,Node*))); 38 | connect(n,SIGNAL(disconnected(Node::Socket*)),this,SLOT(disconnectNode(Node::Socket*))); 39 | connect(n->actionDelete,&QAction::triggered,this,[=](){undoStack.push(new DeleteNodeCommand(n,this));}); 40 | undoStack.push(new AddNodeCommand(n,this)); 41 | } 42 | 43 | void Workspace::addNodes(const QList &n){ 44 | undoStack.beginMacro("add_node"); 45 | for(auto& i: n){ 46 | if(!i) continue; 47 | i->initialPos=i->pos(); 48 | connect(i,SIGNAL(moved()),this,SLOT(moveNodes())); 49 | connect(i,SIGNAL(connected(Node::Socket*,Node*)),this,SLOT(connectNode(Node::Socket*,Node*))); 50 | connect(i,SIGNAL(disconnected(Node::Socket*)),this,SLOT(disconnectNode(Node::Socket*))); 51 | connect(i->actionDelete,&QAction::triggered,this,[=](){undoStack.push(new DeleteNodeCommand(i,this));}); 52 | undoStack.push(new AddNodeCommand(i,this)); 53 | } 54 | undoStack.endMacro(); 55 | } 56 | 57 | void Workspace::paste(){ 58 | clearSelection(); 59 | const QMimeData* mime= QApplication::clipboard()->mimeData(); 60 | if(mime->text()=="Emergence_Nodes"){ 61 | QList nodes; 62 | std::istringstream istr(mime->data("copy").toStdString()); 63 | istr >> nodes; 64 | addNodes(nodes); 65 | } 66 | } 67 | 68 | void Workspace::select_all() const{ 69 | for(const auto& n : items()) 70 | n->setSelected(true); 71 | } 72 | 73 | void Workspace::delete_selected(){ 74 | bool found=false; 75 | for(auto& n:selectedItems()){ 76 | if(((Node*)n)->_type!="output"&&((Node*)n)->_type!="input"){ 77 | if(!found) undoStack.beginMacro("delete"); 78 | found=true; 79 | undoStack.push(new DeleteNodeCommand((Node*)n,this)); 80 | } 81 | } 82 | if(found)undoStack.endMacro(); 83 | } 84 | 85 | void Workspace::moveNodes(){ 86 | undoStack.beginMacro("move"); 87 | for(auto& n: selectedItems()) 88 | undoStack.push(new MoveNodeCommand((Node*)n)); 89 | undoStack.endMacro(); 90 | } 91 | 92 | void Workspace::connectNode(Node::Socket* s, Node* n){ 93 | undoStack.push(new ConnectNodeCommand(s,n)); 94 | } 95 | void Workspace::disconnectNode(Node::Socket* s){ 96 | undoStack.push(new DisconnectNodeCommand(s)); 97 | } 98 | 99 | void Workspace::copy()const{ 100 | QMimeData * mime=new QMimeData; 101 | mime->setText("Emergence_Nodes"); 102 | QList selectedNodes; 103 | for(const auto& i: selectedItems()) 104 | selectedNodes.append((Node*)i); 105 | std::ostringstream oss; 106 | int tmp=selectedNodes.size(); 107 | oss.write(reinterpret_cast(&tmp),sizeof(int)); 108 | for(const auto& n:selectedNodes) 109 | n->toBin(oss); 110 | for(const auto& n:selectedNodes) 111 | for(const auto& nn:n->iNodes){ 112 | tmp= selectedNodes.indexOf(nn); 113 | oss.write(reinterpret_cast(&tmp),sizeof(int)); 114 | } 115 | std::string str= oss.str(); 116 | 117 | QByteArray ba(str.c_str(),str.length()); 118 | mime->setData("copy",ba); 119 | QApplication::clipboard()->setMimeData(mime); 120 | } 121 | 122 | void Workspace::cut(){ 123 | copy(); 124 | delete_selected(); 125 | } 126 | 127 | QList Workspace::nodes()const{ 128 | QList ret; 129 | for(const auto& n:items()) 130 | if(n->data(1)=="countMe") 131 | ret.append((Node*)n); 132 | return ret; 133 | } 134 | int Workspace::count()const{ 135 | return nodes().size(); 136 | } 137 | Node* Workspace::nodeAt(int i) const{ 138 | return nodes().at(i); 139 | } 140 | int Workspace::nodeIndex(Node* n) const{ 141 | return nodes().indexOf(n); 142 | } 143 | void Workspace::toBin(std::ostream& out) const{ 144 | int tmp=nodes().size(); 145 | out.write(reinterpret_cast(&tmp),sizeof(int)); 146 | for(const auto& n:nodes()) 147 | n->toBin(out); 148 | for(const auto& n:nodes()) 149 | for(const auto& nn:n->iNodes){ 150 | tmp= nodes().indexOf(nn); 151 | out.write(reinterpret_cast(&tmp),sizeof(int)); 152 | } 153 | } 154 | void Workspace::toText(std::ostream& out) const{ 155 | out << nodes().size()<< '\n'; 156 | for(const auto& n:nodes()){ 157 | n->toText(out); 158 | out << '\n'; 159 | } 160 | for(const auto& n:nodes()) 161 | for(const auto& nn:n->iNodes) 162 | out << nodes().indexOf(nn) << ' '; 163 | out << '\n'; 164 | } 165 | 166 | void Workspace::fromBin(std::istream& in){ 167 | QList nodes; 168 | in >> nodes; 169 | addNodes(nodes); 170 | } 171 | void Workspace::fromText(std::istream& in){ 172 | QList nodes; 173 | int tmp; 174 | in>>tmp; 175 | 176 | for(int i=0;i> type >>xx >> yy; 180 | Node* n; 181 | n= Node::makeNodeBinTextMethods[type].second(in); 182 | n->setPos(xx,yy); 183 | nodes.push_back(n); 184 | } 185 | for(const auto& n:nodes) 186 | for(uint i=0; inbArgs; i++){ 187 | in>>tmp; 188 | if(tmp>=0) 189 | n->sockets[i]->connectToNode(nodes.at(tmp)); 190 | } 191 | addNodes(nodes); 192 | } 193 | 194 | AddNodeCommand::AddNodeCommand(Node* node, QGraphicsScene* scene, 195 | QUndoCommand* parent): QUndoCommand(parent){ 196 | _scene=scene; 197 | _node=node; 198 | } 199 | void AddNodeCommand::undo(){ 200 | _node->setSelected(false); 201 | _scene->removeItem(_node); 202 | _scene->update(); 203 | } 204 | void AddNodeCommand::redo(){ 205 | _scene->addItem(_node); 206 | _node->setSelected(true); 207 | _node->setZValue(0); 208 | for(const auto& i: _node->collidingItems()) 209 | if(_node->zValue()<= i->zValue()) 210 | _node->setZValue(i->zValue()+1); 211 | _scene->update(); 212 | } 213 | AddNodeCommand::~AddNodeCommand(){ 214 | delete _node; 215 | } 216 | 217 | DeleteNodeCommand::DeleteNodeCommand(Node* node,QGraphicsScene *scene, QUndoCommand *parent):QUndoCommand(parent){ 218 | _scene=scene; 219 | _node=node; 220 | iNodes=node->iNodes; 221 | oConnections=node->oConnections; 222 | } 223 | void DeleteNodeCommand::undo(){ 224 | _scene->addItem(_node); 225 | for(int j=0; jsockets[j]->connectToNode(iNodes[j]); 228 | for(int j=0; jsockets[oConnections[j].second]->connectToNode(_node); 230 | _scene->update(); 231 | } 232 | void DeleteNodeCommand::redo(){ 233 | for(auto& s:_node->sockets) 234 | s->disconnectNode(); 235 | for(auto& c:_node->oConnections) 236 | c.first->sockets[c.second]->disconnectNode(); 237 | _scene->removeItem(_node); 238 | _scene->update(); 239 | } 240 | 241 | ConnectNodeCommand::ConnectNodeCommand(Node::Socket *s, Node *in, 242 | QUndoCommand *parent): QUndoCommand(parent){ 243 | _socket=s; 244 | _iNode=in; 245 | } 246 | void ConnectNodeCommand::undo(){ 247 | _socket->disconnectNode(); 248 | } 249 | void ConnectNodeCommand::redo(){ 250 | _socket->connectToNode(_iNode); 251 | } 252 | 253 | DisconnectNodeCommand::DisconnectNodeCommand(Node::Socket *s, 254 | QUndoCommand *parent): QUndoCommand(parent){ 255 | _node=s->parent->iNodes[s->rank]; 256 | _socket=s; 257 | } 258 | void DisconnectNodeCommand::undo(){ 259 | _socket->connectToNode(_node); 260 | } 261 | void DisconnectNodeCommand::redo(){ 262 | _socket->disconnectNode(); 263 | } 264 | 265 | MoveNodeCommand::MoveNodeCommand(Node* node, 266 | QUndoCommand *parent): QUndoCommand(parent){ 267 | _node=node; 268 | _pos=node->pos(); 269 | _oldPos=node->initialPos; 270 | } 271 | void MoveNodeCommand::undo(){ 272 | _node->setPos(_oldPos); 273 | _node->initialPos=_oldPos; 274 | } 275 | void MoveNodeCommand::redo(){ 276 | _node->setPos(_pos); 277 | _node->initialPos=_pos; 278 | } 279 | -------------------------------------------------------------------------------- /src/Workspace.h: -------------------------------------------------------------------------------- 1 | #ifndef WORKSPACE_H 2 | #define WORKSPACE_H 3 | 4 | #include 5 | #include 6 | #include "Node.h" 7 | 8 | class Workspace : public QGraphicsScene{ 9 | Q_OBJECT 10 | public: 11 | Workspace(QWidget *parent=0); 12 | QUndoStack undoStack; 13 | constexpr static double scaleFactor=1.05; 14 | void addNode(Node*); 15 | void addNode(Node*, const QPointF&); 16 | void addNodes(const QList&); 17 | void toBin(std::ostream&)const; 18 | void toText(std::ostream&)const; 19 | void fromBin(std::istream&); 20 | void fromText(std::istream&); 21 | int count()const; 22 | Node* nodeAt(int)const; 23 | int nodeIndex(Node*)const; 24 | QList nodes()const; 25 | private: 26 | void dragEnterEvent(QGraphicsSceneDragDropEvent *); 27 | void dragMoveEvent(QGraphicsSceneDragDropEvent*); 28 | void dropEvent(QGraphicsSceneDragDropEvent*); 29 | public slots: 30 | void paste(); 31 | void select_all()const; 32 | void delete_selected(); 33 | void copy()const; 34 | void cut(); 35 | void moveNodes(); 36 | void connectNode(Node::Socket*, Node*); 37 | void disconnectNode(Node::Socket*); 38 | }; 39 | 40 | class AddNodeCommand: public QUndoCommand{ 41 | public: 42 | AddNodeCommand(Node* node, QGraphicsScene* scene, 43 | QUndoCommand* parent=0); 44 | ~AddNodeCommand(); 45 | void undo()override; 46 | void redo()override; 47 | private: 48 | Node* _node; 49 | QGraphicsScene* _scene; 50 | }; 51 | 52 | class DeleteNodeCommand: public QUndoCommand{ 53 | public: 54 | DeleteNodeCommand(Node* node,QGraphicsScene* scene, 55 | QUndoCommand* parent=0); 56 | void undo()override; 57 | void redo()override; 58 | private: 59 | Node* _node; 60 | QVector iNodes; 61 | QList> oConnections; 62 | QGraphicsScene* _scene; 63 | }; 64 | 65 | class ConnectNodeCommand: public QUndoCommand{ 66 | public: 67 | ConnectNodeCommand(Node::Socket* s, Node* in, 68 | QUndoCommand* parent=0); 69 | void undo()override; 70 | void redo()override; 71 | private: 72 | Node::Socket* _socket; 73 | Node* _iNode; 74 | }; 75 | 76 | class DisconnectNodeCommand: public QUndoCommand{ 77 | public: 78 | DisconnectNodeCommand(Node::Socket *s, 79 | QUndoCommand* parent=0); 80 | void undo()override; 81 | void redo()override; 82 | private: 83 | Node::Socket* _socket; 84 | Node* _node; 85 | }; 86 | 87 | class MoveNodeCommand: public QUndoCommand{ 88 | public: 89 | MoveNodeCommand(Node *node, QUndoCommand* parent=0); 90 | void undo()override; 91 | void redo()override; 92 | private: 93 | Node* _node; 94 | QPointF _pos; 95 | QPointF _oldPos; 96 | }; 97 | 98 | #endif // WORKSPACE_H 99 | -------------------------------------------------------------------------------- /src/data_t.cpp: -------------------------------------------------------------------------------- 1 | #include "data_t.h" 2 | 3 | data_t::operator bool()const{ 4 | switch (t) { 5 | case TypeEnum::DOUBLE: return d>=1; 6 | case TypeEnum::COLOR: return clr!=0; 7 | case TypeEnum::COMPLEX: return std::real(c)>0 && std::imag(c)>0; 8 | default:return b; 9 | } 10 | } 11 | 12 | data_t::operator double()const{ 13 | switch (t) { 14 | case TypeEnum::BOOL: 15 | return b? 1.0:0.0; 16 | case TypeEnum::COLOR: 17 | return ((clr&0xff)*.0722+ //BLUE 18 | ((clr&0xff00)>>8)*.7152+ //GREEN 19 | ((clr&0xff0000)>>16)*.2126 //RED 20 | )/256.0; 21 | case TypeEnum::COMPLEX: 22 | return std::abs(c); 23 | default: return d; 24 | } 25 | } 26 | 27 | data_t::operator color()const{ 28 | if(t==TypeEnum::BOOL) return b? 0xffffffff:0xff000000; 29 | if(t==TypeEnum::DOUBLE){ 30 | if(d>=1)return 0xffffffff; 31 | if(d<=0)return 0xff000000; 32 | uint8_t c= d*256; 33 | return 0xff000000+c+(c<<8)+(c<<16); 34 | } 35 | if(t==TypeEnum::COMPLEX){ 36 | return QColor::fromHsv(359*(std::arg(c)+M_PI)/(M_PI*2), 37 | 255, 38 | std::abs(c)>1?255:std::abs(c)*255).rgb(); 39 | } 40 | return clr; 41 | } 42 | 43 | data_t::operator cplx()const{ 44 | if(t==TypeEnum::BOOL) return b? 1:0; 45 | if(t==TypeEnum::DOUBLE) return cplx(d,0); 46 | return c; 47 | } 48 | 49 | data_t& data_t::operator=(double dd){ 50 | t=TypeEnum::DOUBLE; 51 | d=dd; 52 | return *this; 53 | } 54 | data_t& data_t::operator=(bool bb){ 55 | t=TypeEnum::BOOL; 56 | b=bb; 57 | return *this; 58 | } 59 | data_t& data_t::operator=(color uu){ 60 | t=TypeEnum::COLOR; 61 | clr=uu; 62 | return *this; 63 | } 64 | data_t& data_t::operator=(QColor uu){ 65 | t=TypeEnum::COLOR; 66 | clr=uu.rgb(); 67 | return *this; 68 | } 69 | data_t& data_t::operator=(cplx cc){ 70 | t=TypeEnum::COMPLEX; 71 | c=cc; 72 | return *this; 73 | } 74 | 75 | data_t operator> (data_t d1, data_t d2){return double(d1)>double(d2);} 76 | data_t operator< (data_t d1, data_t d2){return double(d1)=(data_t d1, data_t d2){return double(d1)>=double(d2);} 80 | data_t operator<=(data_t d1, data_t d2){return double(d1)<=double(d2);} 81 | 82 | data_t operator+ (data_t d1, data_t d2){ 83 | if(d1.t==TypeEnum::COMPLEX||d2.t==TypeEnum::COMPLEX) 84 | return d1.operator cplx()+d2.operator cplx(); 85 | return double(d1)+double(d2); 86 | } 87 | data_t operator- (data_t d1, data_t d2){ 88 | if(d1.t==TypeEnum::COMPLEX||d2.t==TypeEnum::COMPLEX) 89 | return d1.operator cplx()-d2.operator cplx(); 90 | return double(d1)-double(d2); 91 | } 92 | data_t operator* (data_t d1, data_t d2){ 93 | if(d1.t==TypeEnum::COMPLEX||d2.t==TypeEnum::COMPLEX) 94 | return d1.operator cplx()*d2.operator cplx(); 95 | return double(d1)*double(d2); 96 | } 97 | data_t operator/ (data_t d1, data_t d2){ 98 | if(d1.t==TypeEnum::COMPLEX||d2.t==TypeEnum::COMPLEX) 99 | return d1.operator cplx()/d2.operator cplx(); 100 | return double(d1)/double(d2); 101 | } 102 | 103 | data_t data_t::operator-()const{ 104 | if(t==TypeEnum::DOUBLE) return -d; 105 | return -c; 106 | } 107 | 108 | data_t data_t::sin()const{ 109 | if(t==TypeEnum::DOUBLE)return qSin(d); 110 | return std::sin(c); 111 | } 112 | data_t data_t::cos()const{ 113 | if(t==TypeEnum::DOUBLE)return qCos(d); 114 | return std::cos(c); 115 | } 116 | data_t data_t::sqrt()const{ 117 | if(t==TypeEnum::DOUBLE)return qSqrt(d); 118 | return std::sqrt(c); 119 | } 120 | data_t pow(data_t d1, data_t d2){ 121 | if(d1.t==TypeEnum::COMPLEX||d2.t==TypeEnum::COMPLEX) 122 | return std::pow(d1.c,d2.c); 123 | return qPow(d1.d,d2.d); 124 | } 125 | 126 | data_t data_t::log()const{ 127 | if(t==TypeEnum::DOUBLE) return std::log(d); 128 | return std::log(c); 129 | } 130 | -------------------------------------------------------------------------------- /src/data_t.h: -------------------------------------------------------------------------------- 1 | #ifndef DATA_T_H 2 | #define DATA_T_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | enum class TypeEnum{ 9 | BOOL=0x1, 10 | DOUBLE=0x2, 11 | COLOR=0x4, 12 | COMPLEX=0x8, 13 | ANY=0xf 14 | }; 15 | 16 | typedef std::complex cplx; 17 | 18 | struct data_t{ 19 | typedef uint32_t color; 20 | TypeEnum t; 21 | union{ 22 | bool b; 23 | double d; 24 | color clr; 25 | cplx c; 26 | }; 27 | explicit data_t():t(TypeEnum::ANY){} 28 | data_t(double v):t(TypeEnum::DOUBLE), d(v){} 29 | data_t(bool v):t(TypeEnum::BOOL), b(v){} 30 | data_t(unsigned v):t(TypeEnum::COLOR), clr(v){} 31 | data_t(cplx v):t(TypeEnum::COMPLEX), c(v){} 32 | operator bool()const; 33 | operator double()const; 34 | operator color()const; 35 | operator cplx()const; 36 | data_t& operator=(double dd); 37 | data_t& operator=(bool bb); 38 | data_t& operator=(color uu); 39 | data_t& operator=(QColor uu); 40 | data_t& operator=(cplx cc); 41 | data_t operator-()const; 42 | data_t sin()const; 43 | data_t cos()const; 44 | data_t sqrt()const; 45 | data_t log()const; 46 | friend data_t pow(data_t d1, data_t d2); 47 | friend data_t operator> (data_t d1, data_t d2); 48 | friend data_t operator< (data_t d1, data_t d2); 49 | friend data_t operator==(data_t d1, data_t d2); 50 | friend data_t operator!=(data_t d1, data_t d2); 51 | friend data_t operator>=(data_t d1, data_t d2); 52 | friend data_t operator<=(data_t d1, data_t d2); 53 | friend data_t operator+ (data_t d1, data_t d2); 54 | friend data_t operator- (data_t d1, data_t d2); 55 | friend data_t operator* (data_t d1, data_t d2); 56 | friend data_t operator/ (data_t d1, data_t d2); 57 | }; 58 | 59 | #endif // DATA_T_H 60 | -------------------------------------------------------------------------------- /src/emgc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/emgc.ico -------------------------------------------------------------------------------- /src/icons/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/copy.png -------------------------------------------------------------------------------- /src/icons/cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/cut.png -------------------------------------------------------------------------------- /src/icons/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/delete.png -------------------------------------------------------------------------------- /src/icons/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/exit.png -------------------------------------------------------------------------------- /src/icons/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/export.png -------------------------------------------------------------------------------- /src/icons/no_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/no_icon.png -------------------------------------------------------------------------------- /src/icons/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/open.png -------------------------------------------------------------------------------- /src/icons/paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/paste.png -------------------------------------------------------------------------------- /src/icons/redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/redo.png -------------------------------------------------------------------------------- /src/icons/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/save.png -------------------------------------------------------------------------------- /src/icons/undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bsella/Emergence/fdb8f58545ed708bcd9ce670fe85d4a840ddb965/src/icons/undo.png -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mainwindow.h" 3 | 4 | int main(int argc, char *argv[]){ 5 | QApplication a(argc, argv); 6 | MainWindow w; 7 | w.show(); 8 | return a.exec(); 9 | } 10 | -------------------------------------------------------------------------------- /src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | const int MainWindow::_magic_number; 10 | const int MainWindow::_version; 11 | const int MainWindow::_bin_version; 12 | MainWindow::MainWindow(QWidget *parent) : 13 | QMainWindow(parent), 14 | ui(new Ui::MainWindow){ 15 | 16 | ui->setupUi(this); 17 | 18 | QWidget::setWindowTitle("Emergence"); 19 | QWidget::setWindowIcon(QIcon(":/emgc.ico")); 20 | 21 | ui->workspace->setScene(scene=new Workspace); 22 | ui->workspace->setAcceptDrops(true); 23 | ui->workspace->setDragMode(QGraphicsView::DragMode::RubberBandDrag); 24 | 25 | connect(ui->actionCopy,SIGNAL(triggered(bool)),scene,SLOT(copy())); 26 | connect(ui->actionPaste,SIGNAL(triggered(bool)),scene,SLOT(paste())); 27 | connect(ui->actionCut,SIGNAL(triggered(bool)),scene,SLOT(cut())); 28 | connect(ui->actionDelete,SIGNAL(triggered(bool)),scene,SLOT(delete_selected())); 29 | connect(ui->actionSelect_all,SIGNAL(triggered(bool)),scene,SLOT(select_all())); 30 | 31 | connect(ui->actionUndo,SIGNAL(triggered(bool)),&scene->undoStack,SLOT(undo())); 32 | connect(ui->actionRedo,SIGNAL(triggered(bool)),&scene->undoStack,SLOT(redo())); 33 | ui->actionUndo->setEnabled(false); ui->actionRedo->setEnabled(false); 34 | connect(&scene->undoStack,SIGNAL(canUndoChanged(bool)),ui->actionUndo,SLOT(setEnabled(bool))); 35 | connect(&scene->undoStack,SIGNAL(canRedoChanged(bool)),ui->actionRedo,SLOT(setEnabled(bool))); 36 | 37 | // connect(scene,SIGNAL(selectionChanged()),this,SLOT(updateActions())); 38 | // updateActions(); 39 | // ui->actionPaste->setEnabled(QApplication::clipboard()->mimeData()->text()=="Emergence_Nodes"); 40 | // connect(ui->actionCopy,SIGNAL(triggered(bool)),ui->actionPaste,SLOT(setDisabled(bool))); 41 | zoomIN.setShortcut(QKeySequence::ZoomIn); 42 | zoomOUT.setShortcut(QKeySequence::ZoomOut); 43 | connect(&zoomIN,SIGNAL(triggered(bool)),this,SLOT(zoomIn())); 44 | connect(&zoomOUT,SIGNAL(triggered(bool)),this,SLOT(zoomOut())); 45 | addAction(&zoomIN); 46 | addAction(&zoomOUT); 47 | pluginManager= new PluginManager(ui); 48 | if(!pluginManager->loadPlugins()){ 49 | ui->menuInsert->setEnabled(false); 50 | delete ui->toolboxDock; 51 | } 52 | connect(&scene->undoStack,SIGNAL(indexChanged(int)),this,SLOT(updateModified())); 53 | connect(&scene->undoStack,SIGNAL(cleanChanged(bool)),this,SLOT(updateModified())); 54 | } 55 | 56 | MainWindow::~MainWindow(){ 57 | delete ui; 58 | } 59 | void MainWindow::zoomIn()const{ 60 | ui->workspace->scale(Workspace::scaleFactor,Workspace::scaleFactor); 61 | } 62 | void MainWindow::zoomOut()const{ 63 | ui->workspace->scale(1/Workspace::scaleFactor,1/Workspace::scaleFactor); 64 | } 65 | 66 | bool MainWindow::on_actionSave_triggered(){ 67 | if(_filePath=="") 68 | return on_actionSave_as_triggered(); 69 | std::ofstream ofs(_filePath.toStdString()); 70 | 71 | if(_filePath.endsWith(".ebin")){ 72 | ofs.write(reinterpret_cast(&_magic_number),sizeof(uint)); 73 | ofs.write(reinterpret_cast(&_bin_version),sizeof(uint)); 74 | pluginManager->toBin(ofs); 75 | scene->toBin(ofs); 76 | }else{ 77 | ofs << _version << '\n'; 78 | pluginManager->toText(ofs); 79 | scene->toText(ofs); 80 | } 81 | ofs.close(); 82 | 83 | scene->undoStack.setClean(); 84 | return true; 85 | } 86 | bool MainWindow::on_actionSave_as_triggered(){ 87 | QString fileName= QFileDialog::getSaveFileName(ui->workspace,"Save as...",".","Emergence Files (*.e *.ebin)"); 88 | if(fileName.isEmpty()) return false; 89 | if(!fileName.endsWith(".e") && !fileName.endsWith(".ebin")) 90 | fileName.append(".ebin"); 91 | _filePath=fileName; 92 | return on_actionSave_triggered(); 93 | } 94 | void MainWindow::on_actionOpen_triggered(){ 95 | QString fileName= QFileDialog::getOpenFileName(parentWidget(),"Open File",".","Emergence Files (*.e *.ebin)"); 96 | if(fileName.isNull()) return; 97 | 98 | switch (areYouSure()) { 99 | case QMessageBox::Yes: 100 | if(!on_actionSave_triggered()) return; 101 | break; 102 | case QMessageBox::No:break; 103 | case QMessageBox::Cancel:return; 104 | default:break; 105 | } 106 | 107 | scene->select_all(); 108 | scene->undoStack.beginMacro("load"); 109 | scene->delete_selected(); 110 | 111 | std::ifstream ifs(fileName.toStdString()); 112 | int tmp; 113 | if(fileName.endsWith(".e")){ 114 | ifs >> tmp; 115 | if(tmp<_version){ 116 | QMessageBox::warning(0,"Wrong version","Sorry, this save file is too old."); 117 | ifs.close(); 118 | return; 119 | } 120 | pluginManager->fromText(ifs); 121 | scene->fromText(ifs); 122 | }else{ 123 | ifs.read(reinterpret_cast(&tmp),sizeof(uint)); 124 | if(tmp!=_magic_number){ 125 | QMessageBox::warning(0,"Wrong format","Bad File Format"); 126 | ifs.close(); 127 | return; 128 | } 129 | ifs.read(reinterpret_cast(&tmp),sizeof(uint)); 130 | if(tmp<_bin_version){ 131 | QMessageBox::warning(0,"Wrong version","Sorry, this save file is too old."); 132 | ifs.close(); 133 | return; 134 | } 135 | pluginManager->fromBin(ifs); 136 | scene->fromBin(ifs); 137 | } 138 | 139 | scene->undoStack.endMacro(); 140 | scene->clearSelection(); 141 | ifs.close(); 142 | _filePath=fileName; 143 | scene->undoStack.setClean(); 144 | } 145 | 146 | void MainWindow::updateModified(){ 147 | fileModified=!scene->undoStack.isClean(); 148 | QString title = "Emergence"; 149 | if(_filePath!="") 150 | title+=" - "+_filePath.split('/').back(); 151 | if(fileModified) 152 | title+="*"; 153 | setWindowTitle(title); 154 | } 155 | 156 | void MainWindow::on_actionNew_triggered(){ 157 | switch (areYouSure()) { 158 | case QMessageBox::Yes: 159 | if(!on_actionSave_triggered()) return; 160 | break; 161 | case QMessageBox::No:break; 162 | case QMessageBox::Cancel:return; 163 | default:break; 164 | } 165 | scene->undoStack.clear(); 166 | scene->undoStack.setClean(); 167 | _filePath=""; 168 | updateModified(); 169 | } 170 | 171 | void MainWindow::on_actionExit_triggered(){ 172 | close(); 173 | } 174 | int MainWindow::areYouSure(){ 175 | if(fileModified){ 176 | return QMessageBox::question(this,"Save changes", 177 | "Save changes to "+_filePath+" before closing?", 178 | (QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel)); 179 | } 180 | return QMessageBox::No; 181 | } 182 | void MainWindow::closeEvent(QCloseEvent*event){ 183 | switch (areYouSure()){ 184 | case QMessageBox::Yes: 185 | if(!on_actionSave_triggered()) 186 | event->ignore(); 187 | break; 188 | case QMessageBox::No:break; 189 | case QMessageBox::Cancel: 190 | event->ignore(); 191 | break; 192 | default: 193 | break; 194 | } 195 | } 196 | //void MainWindow::updateActions(){ 197 | // ui->actionExport->setEnabled(false); 198 | // bool someNodeIsSelected=false; 199 | // for(auto& n: scene->selectedItems()){ 200 | // if(((Node*)n)->id!=Node::OUTPUT_G &&((Node*)n)->id!=Node::INPUT_G) 201 | // someNodeIsSelected=true; 202 | // if(((Node*)n)->id==Node::RENDER_G){ 203 | // ui->actionExport->setEnabled(true); 204 | // break; 205 | // } 206 | // } 207 | // ui->actionCut->setEnabled(someNodeIsSelected); 208 | // ui->actionCopy->setEnabled(someNodeIsSelected); 209 | // ui->actionDelete->setEnabled(someNodeIsSelected); 210 | //} 211 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | #include "Workspace.h" 7 | #include "PluginManager.h" 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow{ 14 | Q_OBJECT 15 | 16 | public: 17 | explicit MainWindow(QWidget *parent = 0); 18 | ~MainWindow(); 19 | Ui::MainWindow *ui; 20 | private: 21 | static const int _magic_number=0xa1b2affd; 22 | static const int _version=6; 23 | static const int _bin_version=0; 24 | Workspace* scene; 25 | PluginManager *pluginManager; 26 | QAction zoomIN, zoomOUT; 27 | QString _filePath=""; 28 | bool fileModified=false; 29 | void closeEvent(QCloseEvent*)override; 30 | int areYouSure(); 31 | private slots: 32 | // void updateActions(); 33 | void zoomIn()const; 34 | void zoomOut()const; 35 | void updateModified(); 36 | 37 | void on_actionNew_triggered(); 38 | void on_actionOpen_triggered(); 39 | bool on_actionSave_triggered(); 40 | bool on_actionSave_as_triggered(); 41 | void on_actionExit_triggered(); 42 | }; 43 | 44 | #endif // MAINWINDOW_H 45 | -------------------------------------------------------------------------------- /src/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 641 10 | 493 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 0 27 | 0 28 | 641 29 | 20 30 | 31 | 32 | 33 | 34 | Insert 35 | 36 | 37 | 38 | 39 | File 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Edit 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Tools 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 190 76 | 237 77 | 78 | 79 | 80 | false 81 | 82 | 83 | QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable 84 | 85 | 86 | Toolbox 87 | 88 | 89 | 1 90 | 91 | 92 | 93 | 94 | QLayout::SetMinimumSize 95 | 96 | 97 | 2 98 | 99 | 100 | 0 101 | 102 | 103 | 0 104 | 105 | 106 | 0 107 | 108 | 109 | 110 | 111 | -1 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | :/icons/exit.png:/icons/exit.png 122 | 123 | 124 | Exit 125 | 126 | 127 | Ctrl+Q 128 | 129 | 130 | 131 | 132 | Save As... 133 | 134 | 135 | Ctrl+Shift+S 136 | 137 | 138 | 139 | 140 | 141 | :/icons/open.png:/icons/open.png 142 | 143 | 144 | Open 145 | 146 | 147 | Ctrl+O 148 | 149 | 150 | 151 | 152 | 153 | :/icons/undo.png:/icons/undo.png 154 | 155 | 156 | Undo 157 | 158 | 159 | Ctrl+Z 160 | 161 | 162 | 163 | 164 | 165 | :/icons/redo.png:/icons/redo.png 166 | 167 | 168 | Redo 169 | 170 | 171 | Ctrl+Shift+Z 172 | 173 | 174 | 175 | 176 | 177 | :/icons/cut.png:/icons/cut.png 178 | 179 | 180 | Cut 181 | 182 | 183 | Ctrl+X 184 | 185 | 186 | 187 | 188 | 189 | :/icons/copy.png:/icons/copy.png 190 | 191 | 192 | Copy 193 | 194 | 195 | Ctrl+C 196 | 197 | 198 | 199 | 200 | 201 | :/icons/paste.png:/icons/paste.png 202 | 203 | 204 | Paste 205 | 206 | 207 | Ctrl+V 208 | 209 | 210 | 211 | 212 | 213 | :/icons/delete.png:/icons/delete.png 214 | 215 | 216 | Delete 217 | 218 | 219 | Del 220 | 221 | 222 | 223 | 224 | Select All 225 | 226 | 227 | Ctrl+A 228 | 229 | 230 | 231 | 232 | 233 | :/icons/save.png:/icons/save.png 234 | 235 | 236 | Save 237 | 238 | 239 | Ctrl+S 240 | 241 | 242 | 243 | 244 | New 245 | 246 | 247 | Ctrl+N 248 | 249 | 250 | 251 | 252 | 253 | 254 | NodeBox 255 | QWidget 256 |
NodeBox.h
257 | 1 258 |
259 |
260 | 261 | workspace 262 | 263 | 264 | 265 | 266 | 267 |
268 | -------------------------------------------------------------------------------- /src/signalManager.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNALMANAGER_H 2 | #define SIGNALMANAGER_H 3 | 4 | #include 5 | 6 | class SignalManager: public QObject{ 7 | Q_OBJECT 8 | public: 9 | SignalManager(){} 10 | ~SignalManager(){} 11 | signals: 12 | void updateRatio(); 13 | void updateOutputs(); 14 | void nbArgChanged(void*,uint); 15 | }; 16 | 17 | #endif // SIGNALMANAGER_H 18 | -------------------------------------------------------------------------------- /src/src.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | emgc.ico 4 | icons/copy.png 5 | icons/cut.png 6 | icons/delete.png 7 | icons/exit.png 8 | icons/export.png 9 | icons/no_icon.png 10 | icons/open.png 11 | icons/paste.png 12 | icons/redo.png 13 | icons/save.png 14 | icons/undo.png 15 | 16 | 17 | --------------------------------------------------------------------------------