1#!/usr/bin/env php 2# 3# this file takes the formulas in formula/definition and does a couple of things: 4# - generates the information boxes in the ui from the source code 5# - generates opencl formulas 6# - generates formula thumbnails and configs 7# - write a csv file which contains a table of all formulas 8# 9# requires packages: highlight, clang-format, git and php (apt-get install highlight clang-format git php5-cli) 10# clang-format is required in version 3.8.1, get executable from here: http://releases.llvm.org/download.html 11# 12# on default this script runs dry, 13# it will try to parse all formulas and show which ui files would be modified 14# this should always be run first, to see if any issues occur 15# if you invoke this script with "nondry" as cli argument it will write changes to ui files 16# if you invoke this script with "checkCl" as cli argument it will also check formula opencl file compilability (slow) 17# 18 19<?php 20require_once(dirname(__FILE__) . '/common.inc.php'); 21printStart(); 22 23printStartGroup('READING FORMULA DATA'); 24$formulas = getFormulasData(); 25$formulaExampleUsage = getFormulaExampleUsage(); 26 27printStartGroup('RUNNING FORMULA CHECKS'); 28foreach ($formulas as $index => $formula) { 29 @$i++; 30 $success = true; 31 $status = array(); 32 if ($success) $success = updateInfoBoxes($index, $formula, $status); 33 if ($success) $success = generateFormulaOpenCLFiles($formula, $status); 34 if ($success) $success = generateFormulaIcons($formula, $status); 35 if ($success && argumentContains('checkCl')) $success = checkOpenCLCompile($formula, $status); 36 printResultLine($formula['nameInComboBox'], $success, $status, $i / count($formulas)); 37} 38printEndGroup(); 39if (!isDryRun()) writeFormulaCSV($formulas); 40if (!isDryRun()) writeParameterNamesTxt(); 41if (!isDryRun()) writeFractalDefinitionFile($formulas); 42printFinish(); 43exit; 44 45 46function getFormulasData() 47{ 48 $formulas = array(); 49 $indexIdLookup = getIndexIdLookUp(); 50 51 foreach (glob(PROJECT_PATH . 'formula/definition/*.cpp') as $key => $file) { 52 if(strpos($file, 'abstract_fractal.cpp') !== false) continue; 53 if(strpos($file, 'all_fractal_list.cpp') !== false) continue; 54 if(strpos($file, 'legacy_fractal_transforrms.cpp') !== false) continue; 55 if(strpos($file, 'fractal_none.cpp') !== false) continue; 56 57 //echo 'Processing file ' . $file . PHP_EOL; 58 59 $fractalCppFile = file_get_contents($file); 60 // read index and name from fractal_list 61 preg_match('/cAbstractFractal\(\)\n{([\s\S]*?)\n}/', $fractalCppFile, $match); 62 $definitionPart = @$match[1]; 63 $definitionPartLinesRaw = explode(PHP_EOL, trim($definitionPart)); 64 // strip comment lines 65 $definitionPartLines = array_filter($definitionPartLinesRaw, function($l) { 66 return !preg_match('/\s*\/\/.*/', $l); 67 }); 68 if (count($definitionPartLines) != 9) die('could not read index for formula : ' . $file . ' --> ' . print_r($definitionPartLinesRaw, true)); 69 $f = array(); 70 foreach($definitionPartLines as $definitionPartLine){ 71 if(!preg_match('/([a-zA-Z]+)\s*=\s*"?([\da-zA-Z\.: -_]*?)"?;/', $definitionPartLine, $matchLine)) 72 die('Line wrong for ' . $file . ' --> ' . $definitionPartLine); 73 $f[$matchLine[1]] = $matchLine[2]; 74 } 75 $index = str_replace('fractal::', '', $f['internalID']); 76 77 $internalNameNew = from_camel_case($index); 78 79 //echo $index . ' ' . $internalNameNew . PHP_EOL; 80 81 // check for automatic renaming to fit naming convention 82 if ($internalNameNew != $f['internalName']) { 83 if (!isDryRun()) { 84 upgradeInternalName($f['internalName'], $internalNameNew); 85 } 86 echo noticeString('internal name upgrade from ' . $f['internalName'] . ' to ' . $internalNameNew) . PHP_EOL; 87 $f['internalName'] = $internalNameNew; 88 if (!isDryRun()) die('Changes have been written, check changes and run script again for more changes.'); 89 } 90 91 // read function contents 92 $functionContentMatchString = '/\+\+\+\n\s\*(\n[\s\S]+?\*\/)[\S\s]*(FormulaCode\([\s\S]*})/'; 93 94 //echo $functionContentMatchString . PHP_EOL; 95 96 $functionContentFound = false; 97 $code = false; 98 $comment = false; 99 $rawComment = false; 100 101 if (preg_match($functionContentMatchString, $fractalCppFile, $matchFunctionContent)) { 102 $functionContentFound = true; 103 $rawComment = $matchFunctionContent[1]; 104 $comment = parseComment(trim($matchFunctionContent[1])); 105 $code = $matchFunctionContent[2]; 106 $code = trim(str_replace('FormulaCode', 'void ' . ucfirst($index) . 'Iteration', $code)); 107 } 108 109 if (!$functionContentFound) { 110 echo errorString('Warning, could not read code for index: ' . $index) . PHP_EOL; 111 continue; 112 // die('could not read code for index: ' . $index); 113 } 114 115 $formulas[$index] = array_merge($f, array( 116 'uiFile' => PROJECT_PATH . 'formula/ui/' . $f['internalName'] . '.ui', 117 'definitionFileName' => basename($file), 118 'code' => $code, 119 'comment' => $comment, 120 'rawComment' => $rawComment, 121 'id' => $indexIdLookup[$index], 122 'openclFile' => PROJECT_PATH . 'formula/opencl/' . $f['internalName'] . '.cl', 123 'definitionFile' => PROJECT_PATH . 'formula/definition/fractal_' . $f['internalName'] . '.cpp', 124 'openclCode' => parseToOpenCL($code), 125 'type' => (strpos($f['internalName'], 'transf_') !== false ? 'transf' : 'formula'), 126 )); 127 // print_r($formulas); 128 } 129 return $formulas; 130} 131 132// update information boxes in the ui 133function updateInfoBoxes($index, $formula, &$status) 134{ 135 if($index == 'custom') return; // nothing to do for the custom opencl formula 136 global $formulaExampleUsage; 137 $formattedEscapedCode = getFormatCode($formula['code']); 138 // remove hardcoded font-size, to use system defined font-size 139 $formattedEscapedCode = str_replace('font-size:10pt;', '', $formattedEscapedCode); 140 141 // extract only body element, since html part and comment change between versions of highlight 142 $startCode = strpos($formattedEscapedCode, '<body'); 143 $endCode = strpos($formattedEscapedCode, '</body>') + strlen('</body>'); 144 $formattedEscapedCode = substr($formattedEscapedCode, $startCode, $endCode - $startCode); 145 146 $comment = $formula['comment']; 147 $informationText = ''; 148 if (!empty($comment['description'])) { 149 $informationText = '<p>' . implode('<br>', $comment['description']) . '</p>'; 150 } 151 $informationText .= "<table>" . PHP_EOL; 152 // $informationText .= "<tr><th>Name</th><td>" . $formula['nameInComboBox'] . "</td></tr>" . PHP_EOL; 153 154 if (!empty($comment['reference'])) { 155 $informationText .= '<tr><th>Reference</th><td>'; 156 foreach ($comment['reference'] as $ref) { 157 $informationText .= "<a href=\"" . $ref . "\">" . $ref . "<br>" . PHP_EOL; 158 } 159 $informationText .= '</td></tr>' . PHP_EOL; 160 } 161 if (!empty($comment['author'])) { 162 $informationText .= '<tr><th>Author</th><td>'; 163 foreach ($comment['author'] as $author) { 164 $informationText .= $author . "<br>" . PHP_EOL; 165 } 166 $informationText .= '</td></tr>' . PHP_EOL; 167 } 168 $informationText .= "</table>" . PHP_EOL; 169 if (array_key_exists($formula['id'], $formulaExampleUsage)) { 170 $informationText .= '<br><b>Examples using this formula</b><br>'; 171 $exampleFilenames = $formulaExampleUsage[$formula['id']]; 172 if (count($exampleFilenames) > 5) { // do not show more than 5 examples 173 array_splice($exampleFilenames, 5); 174 $exampleFilenames[] = '...'; 175 } 176 $informationText .= implode('<br>', $exampleFilenames); 177 } else { 178 if (isWarning()) { 179 $status[] = warningString('formula ' . $formula['nameInComboBox'] . ' is not used in any examples yet.'); 180 } 181 } 182 183 $informationText .= "<h3>Code</h3>" . PHP_EOL; 184 185 $uiFileContent = file_get_contents($formula['uiFile']); 186 $regexInformation = '/(<widget class="MyGroupBox" name="groupCheck_info">[\s\S]+?)<item>[\s\S]+?<\/layout>/'; 187 188 $replacement = '$1<item> 189 <widget class="QLabel" name="label_information_general"> 190 <property name="text"> 191 <string notr="true">' . htmlentities($informationText) . '</string> 192 </property> 193 <property name="wordWrap"> 194 <bool>true</bool> 195 </property> 196 <property name="openExternalLinks"> 197 <bool>true</bool> 198 </property> 199 <property name="textInteractionFlags"> 200 <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> 201 </property> 202 </widget> 203 </item> 204 <item> 205 <widget class="QLabel" name="label_code_content"> 206 <property name="styleSheet"> 207 <string notr="true">border-style: outset; border-width: 2px; border-radius: 3px; border-color: black; background-color: #fff5ee; padding: 4px;</string> 208 </property> 209 <property name="text"> 210 <string notr="true">' . htmlentities($formattedEscapedCode) . '</string> 211 </property> 212 <property name="wordWrap"> 213 <bool>true</bool> 214 </property> 215 <property name="openExternalLinks"> 216 <bool>true</bool> 217 </property> 218 <property name="textInteractionFlags"> 219 <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> 220 </property> 221 </widget> 222 </item> 223 </layout>'; 224 $newUiFileContent = preg_replace($regexInformation, $replacement, $uiFileContent, -1, $count); 225 $newUiFileContent = preg_replace('/<class>.+<\/class>/', '<class>' . $formula['internalName'] . '</class>', $newUiFileContent, 1); 226 $postitionOfWindowTitle = strpos($newUiFileContent, 'windowTitle '); 227 $postitionOfWindowTitleStringStart = strpos($newUiFileContent, '<string', $postitionOfWindowTitle); 228 $postitionOfWindowTitleStringEnd = strpos($newUiFileContent, '</string>', $postitionOfWindowTitle) + strlen('</string>'); 229 $newUiFileContent = substr_replace($newUiFileContent, '<string notr="true">' . $formula['internalName'] . '</string>', 230 $postitionOfWindowTitleStringStart, $postitionOfWindowTitleStringEnd - $postitionOfWindowTitleStringStart); 231 if ($count == 0) { 232 $status[] = errorString('Warning, could not replace code in ui file for index: ' . $index) . PHP_EOL; 233 return false; 234 } 235 236 $replaceFormulaLookup = array( 237 array('find' => '/\>\s*([^<]+?)\s*<\/string>/', 'replace' => '>$1</string>'), // whitespace fix 1 238 array('find' => '/\>\s*([^<]+?)\s*:\s*<\/string>/', 'replace' => '>$1:</string>'), // whitespace fix 2 239 array('find' => '/<string>(.*?)\s+(\s.*?)<\/string>/', 'replace' => '<string>$1$2</string>'), // whitespace fix 3, stop those whitespaces! :) 240 array('find' => '/<string>fabs\s*\(\s*(.*?)\s*\)\s*<\/string>/', 'replace' => '<string>abs($1)</string>'), 241 array('find' => '/<string>abs\s*\(\s*(.*?)\s*\)\s*<\/string>/', 'replace' => '<string>abs($1)</string>'), 242 array('find' => '/<string>(.*?)::(.*?)<\/string>/', 'replace' => '<string>$1:$2</string>'), 243 array('find' => '/<string>Menger Scale<\/string>/', 'replace' => '<string>Menger Scale:</string>'), 244 array('find' => '/<string>Menger offsets:<\/string>/', 'replace' => '<string>Menger Offset:</string>'), 245 array('find' => '/<string>DE tweak temp<\/string>/', 'replace' => '<string>DE tweak temp:</string>'), 246 array('find' => '/<string>Offset<\/string>/', 'replace' => '<string>Offset:</string>'), 247 array('find' => '/Rotation;<\/string>/', 'replace' => 'Rotation</string>'), 248 array('find' => '/>Multiplier<\/string>/', 'replace' => '>Multiplier:</string>'), 249 array('find' => '/>Cpixel Multiplier<\/string>/', 'replace' => '>Cpixel Multiplier:</string>'), 250 array('find' => '/>Addition Constant<\/string>/', 'replace' => '>Addition Constant:</string>'), 251 array('find' => '/>DE Tweak<\/string>/', 'replace' => '>DE Tweak:</string>'), 252 array('find' => '/>Post_scale<\/string>/', 'replace' => '>Post Scale:</string>'), 253 array('find' => '/>Pre_scale<\/string>/', 'replace' => '>Pre Scale:</string>'), 254 array('find' => '/class="QCheckBox"/', 'replace' => 'class="MyCheckBox"'), 255 ); 256 foreach ($replaceFormulaLookup as $item) { 257 $newUiFileContent = preg_replace($item['find'], $item['replace'], $newUiFileContent); 258 } 259 260 // untranslatable and remove double point 261 $notrRemoveDoublePointCI = array( 262 'z\.x', 'z\.y', 'z\.z', 'z\.w', 263 'c\.x', 'c\.y', 'c\.z', 'c\.w', 264 'xyz', 'xzy', 'yxz', 'yzx', 'zxy', 'zyx', 265 'x', 'y', 'z', 'w', 266 'xy', 'yx', 'xz', 'zx', 'yz', 'zy', 267 'xw', 'yw', 'zw', 268 'alpha', 'beta', 'gamma', 269 'fabs', 'fabs\(z\.x\)', 'fabs\(z\.y\)', 'fabs\(z\.z\)', 'fabs\(z\)', 270 'abs', 'abs\(x\)', 'abs\(y\)', 'abs\(z\)', 271 'T1', 'T1mod', 'T2', 'T3', 'T4', 'T5b', 272 'asin', 'acos', 'atan', 'atan2', 273 ); 274 275 foreach ($notrRemoveDoublePointCI as $item) { 276 $newUiFileContent = preg_replace('/<string>' . $item . ':*;*<\/string>/i', 277 '<string notr="true">' . str_replace('\\', '', $item) . '</string>', $newUiFileContent); 278 } 279 280 // simple find and replace whole string 281 $simpleReplace = array( 282 array('find' => 'Type 4 Fold Value', 'replace' => 'Type 4 Fold value:'), 283 array('find' => 'Type 5 Fold2 Value', 'replace' => 'Type 5 Fold2 value:'), 284 ); 285 286 foreach ($simpleReplace as $item) { 287 $newUiFileContent = str_replace($item['find'], $item['replace'], $newUiFileContent); 288 } 289 290 if ($newUiFileContent == $uiFileContent) { 291 return true; 292 } 293 if (!isDryRun()) { 294 file_put_contents($formula['uiFile'], $newUiFileContent); 295 } 296 $status[] = noticeString('ui file changed'); // . (' . basename($formula['uiFile']) . ') 297 return true; 298} 299 300// generate opencl formulas 301function generateFormulaOpenCLFiles($formula, &$status) 302{ 303 // TODO add primitives 304 $modInterval = getModificationInterval($formula['openclFile'], true); 305 $fileHeader = '/** 306 * Mandelbulber v2, a 3D fractal generator _%}}i*<. ____ _______ 307 * Copyright (C) ' . $modInterval . ' Mandelbulber Team _>]|=||i=i<, / __ \___ ___ ___ / ___/ / 308 * \><||i|=>>%) / /_/ / _ \/ -_) _ \/ /__/ /__ 309 * This file is part of Mandelbulber. )<=i=]=|=i<> \____/ .__/\__/_//_/\___/____/ 310 * The project is licensed under GPLv3, -<>>=|><|||` /_/ 311 * see also COPYING file in this folder. ~+{i%+++ 312 * ' . str_replace(array('/**', '*/'), '', $formula['rawComment']) . ' 313 * This file has been autogenerated by tools/populateUiInformation.php 314 * from the file "' . $formula['definitionFileName'] . '" in the folder formula/definition 315 * D O N O T E D I T T H I S F I L E ! 316 */' . PHP_EOL; 317 318 $openclContent = @file_get_contents($formula['openclFile']); 319 $newOpenCLContent = $fileHeader . PHP_EOL; 320 $newOpenCLContent .= $formula['openclCode']; 321 322 // clang-format 323 $filepathTemp = PROJECT_PATH . '/tools/.tmp.c'; 324 file_put_contents($filepathTemp, $newOpenCLContent); 325 shell_exec(CLANG_FORMAT_EXEC_PATH . ' -i --style=file ' . escapeshellarg($filepathTemp)); 326 $newOpenCLContent = file_get_contents($filepathTemp); 327 unlink($filepathTemp); // nothing to see here :) 328 329 $newOpenCLContentWithoutDateLine = preg_replace('/Copyright\s\(C\)\s\d+/', '', $newOpenCLContent); 330 $openclContentWithoutDateLine = preg_replace('/Copyright\s\(C\)\s\d+/', '', $openclContent); 331 332 if ($newOpenCLContentWithoutDateLine == $openclContentWithoutDateLine) { 333 return true; 334 } 335 if (!isDryRun()) { 336 file_put_contents($formula['openclFile'], $newOpenCLContent); 337 // file_put_contents($formula['openclFile'] . '.orig', $formula['code']); 338 } 339 $status[] = noticeString('opencl file changed'); // (' . basename($formula['openclFile']) . ') 340 return true; 341} 342 343// generate formula icons 344function generateFormulaIcons($formula, &$status) 345{ 346 // autogenerate missing formula and transform images 347 $imgPath = PROJECT_PATH . 'formula/img/' . $formula['internalName'] . '.png'; 348 if (file_exists($imgPath)) { 349 return true; 350 } 351 352 if (!isDryRun()) { 353 if (generate_formula_icon($formula, $imgPath)) { 354 $status[] = successString('image generated.'); 355 return true; 356 } else { 357 $status[] = noticeString('image not generated. Maybe Mandelbulber not found?'); 358 return true; 359 } 360 } else { 361 $status[] = noticeString('image does not exist'); 362 return true; 363 } 364} 365 366function checkOpenCLCompile($formula, &$status) 367{ 368 $checkOpenCLCompileCmd = 'clang -c -S -emit-llvm -o test.ll -w -include clc/clc.h -Dcl_clang_storage_class_specifiers -x cl'; 369 $checkOpenCLCompileCmd .= ' -include ' . PROJECT_PATH . 'opencl/cl_kernel_include_headers.h'; 370 $checkOpenCLCompileCmd .= ' -o /dev/null'; // -S -emit-llvm 371 $checkOpenCLCompileCmd .= ' -DOPENCL_KERNEL_CODE -I' . PROJECT_PATH . 'opencl/'; 372 $checkOpenCLCompileCmd .= ' ' . $formula['openclFile'] . ' 2>&1'; 373 exec($checkOpenCLCompileCmd, $output, $ret); 374 if ($ret != 0) { 375 $status[] = errorString('formula opencl file broken! ' . (!isVerbose() ? 'see error with verbose mode' : '')); 376 if (isVerbose()) $status[] = print_r($output); 377 return false; 378 } 379 return true; 380} 381 382function getFormatCode($code) 383{ 384 $cmd = "echo " . escapeshellarg($code); 385 $cmd .= " | sed 's/ / /g' "; // replace tab with double space 386 $cmd .= " | highlight -O html --style seashell --inline-css --syntax cpp"; 387 return shell_exec($cmd); 388} 389 390function parseComment($c) 391{ 392 $lines = explode(PHP_EOL, $c); 393 $out = array(); 394 $tag = 'description'; 395 foreach ($lines as $l) { 396 $line = trim($l); 397 if (in_array($line, array('/**', '*/'))) continue; 398 if (preg_match("/\*[\s]+@([\S]+)[\s]*(.*)/", $line, $match)) { 399 $tag = $match[1]; 400 if (!array_key_exists($tag, $out)) $out[$tag] = array(); 401 $text = trim($match[2]); 402 if ($text != '' || count($out[$tag]) > 0) { 403 $out[$tag][] = $match[2]; 404 } 405 } else if (preg_match("/\*[\s]+(.*)/", $line, $match)) { 406 $out[$tag][] = $match[1]; 407 } else { 408 $out[$tag][] = ''; 409 } 410 } 411 return $out; 412} 413 414function getFormulaExampleUsage() 415{ 416 // get a lookup for every formula in which example files it is used 417 $exampleBasePath = PROJECT_PATH . 'deploy/share/mandelbulber2/examples/'; 418 $exampleFileMasks[] = $exampleBasePath . '*.fract'; 419 $exampleFileMasks[] = $exampleBasePath . '*/*.fract'; 420 $formulaExampleUsage = array(); 421 foreach ($exampleFileMasks as $exampleFileMask) { 422 foreach (glob($exampleFileMask) as $exampleFileName) { 423 $exampleContent = file_get_contents($exampleFileName); 424 $exampleContentLines = explode(PHP_EOL, $exampleContent); 425 $pathOfFileFromExamples = str_replace($exampleBasePath, '', $exampleFileName); 426 427 foreach ($exampleContentLines as $line) { 428 $line = trim($line); 429 if (preg_match("/^formula_\d+\s(\d+);$/", $line, $match)) { 430 if (!array_key_exists($match[1], $formulaExampleUsage)) $formulaExampleUsage[$match[1]] = array(); 431 if (!in_array($pathOfFileFromExamples, $formulaExampleUsage[$match[1]])) { 432 $formulaExampleUsage[$match[1]][] = $pathOfFileFromExamples; 433 } 434 } 435 } 436 } 437 } 438 return $formulaExampleUsage; 439} 440 441function getIndexIdLookUp() 442{ 443 // get the integer id from fractal_list.hpp for the named index of each formula 444 $fractalListHeaderContent = file_get_contents(PROJECT_PATH . 'formula/definition/all_fractal_list_enums.hpp'); 445 $indexIdLookUp = array(); 446 $fractalListHeaderContentLines = explode(PHP_EOL, $fractalListHeaderContent); 447 foreach ($fractalListHeaderContentLines as $line) { 448 $line = trim($line); 449 if (preg_match("/^(\w+)\s=\s(\d+),.*$/", $line, $match)) { 450 $indexIdLookUp[$match[1]] = $match[2]; 451 } 452 } 453 return $indexIdLookUp; 454} 455 456function parseToOpenCL($code, $mode = 'single') 457{ 458 // $fod = $mode == 'single' ? 'float' : 'double'; 459 $fod = 'REAL'; 460 $var = '[A-Za-z_][A-Za-z0-9\.\-\>_\[\]]*'; // regex for a var name 461 $functionName = '[A-Za-z_][A-Za-z0-9\.\-\>_]*'; // regex for a function name 462 $double = '(?:-?\d+\.?\d*(?:[eE][+-]?\d+)?|-?\d*\.?\d+(?:[eE][+-]?\d+)?)'; // regex for a double value 463 $float = $double . 'f'; // regex for a float value 464 $nb = "[^()]*"; // matches everything but braces 465 $br = "-?(?:$functionName)?\($nb\)"; // regex for a simply braced expression with optional function invocation 466 $br1_1 = "\($nb$br$nb\)"; // regex for a double braced expression (one inner brace) 467 $br1_2 = "\($nb$br$nb$br$nb\)"; // regex for a double braced expression (two inner braces) 468 $s = '[\n\r\s]+'; // any whitespace including new lines 469 $all = '[\S\s]+?'; // anything including new lines as few as possible (mark end with next operator) 470 $rval = "$br1_2|$br1_1|$br|$float|-?$var"; // any of those types can be an "assignable expression" 471 $preF = "\s|\(|\{|-"; // these chars can occur befire a function 472 $multChain = "(?:(?:$rval)$s\*$s)*(?:$rval)"; // a chain of multiplicated expressions 473 // see here for all possible: https://www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/mathFunctions.html 474 $cppToOpenCLReplaceLookup = array( 475 array('find' => '/double/', 'replace' => $fod), // all doubles to floats 476 array('find' => "/([\s\(\{])($double)([\s\)\};,])/", 'replace' => '$1$2' . ($mode == 'single' ? 'f' : '') . '$3'), // double literals to float literals 477 array('find' => "/($preF)sin\(/", 'replace' => '$1native_sin('), // native sin 478 array('find' => "/($preF)cos\(/", 'replace' => '$1native_cos('), // native cos 479 array('find' => "/($preF)pow\(/", 'replace' => '$1native_powr('), // native pow 480 array('find' => "/($preF)sqrt\(/", 'replace' => '$1native_sqrt('), // native sqrt 481 array('find' => "/CVector3\(($multChain,$s$multChain,$s$multChain)\)/", 'replace' => '(' . $fod . '3) {$1}'), // CVector3 to built in float3 482 array('find' => "/CVector3\(\)/", 'replace' => '(' . $fod . '3) {0, 0, 0}'), // CVector3 default constructor to built in float3 483 array('find' => "/CVector3\(($all)\);/", 'replace' => '(' . $fod . '3) {$1};'), // CVector3 to built in float3 484 array('find' => "/CVector3(\s)/", 'replace' => $fod . '3$1'), // CVector3 to built in float3 485 array('find' => "/CVector4\(\)/", 'replace' => '(' . $fod . '4) {0, 0, 0, 0}'), // CVector3 default constructor to built in float3 486 array('find' => "/CVector4\(($multChain),($s$multChain)\)/", 'replace' => '(' . $fod . '4) {$1.x,$1.y,$1.z,$2}'), // CVector4 construct by CVector3 and float to built in construct 487 array('find' => "/CVector4\(($multChain,$s$multChain,$s$multChain,$s$multChain)\)/", 'replace' => '(' . $fod . '4) {$1}'), // CVector4 to built in float4 488 array('find' => "/CVector4\(($all)\);/", 'replace' => '(' . $fod . '4) {$1};'), // CVector4 to built in float4 489 array('find' => "/CVector4(\s)/", 'replace' => $fod . '4$1'), // CVector4 to built in float4 490 array('find' => "/($var)\.Length\(\)/", 'replace' => 'length($1)'), // CVector3 Length() to built in length 491 array('find' => "/($var)\.Dot\(/", 'replace' => 'dot($1, '), // CVector3 Dot() to built in dot 492 array('find' => "/($var)\.Cross\(/", 'replace' => 'cross($1, '), // CVector3 Cross() to built in cross 493 array('find' => "/($var)\.RotateVector\(/", 'replace' => 'Matrix33MulFloat4($1, '), // CRotationMatrix33 to custom rotation function 494 array('find' => "/($var)\.RotateX\(/", 'replace' => '$1 = RotateX($1, '), // CRotationMatrix33 to custom rotation function 495 array('find' => "/($var)\.RotateY\(/", 'replace' => '$1 = RotateY($1, '), // CRotationMatrix33 to custom rotation function 496 array('find' => "/($var)\.RotateZ\(/", 'replace' => '$1 = RotateZ($1, '), // CRotationMatrix33 to custom rotation function 497 array('find' => "/($var)\.RotateAroundVectorByAngle\(/", 'replace' => 'RotateAroundVectorByAngle4($1, '), // CVector3 to custom rotation function 498 array('find' => "/($var)\.GetXYZ\(\)/", 'replace' => '$1.xyz'), // CVector4 getxyz to native accessor of float4 499 array('find' => "/CRotationMatrix$s($var);/", 'replace' => 'matrix33 $1;' . PHP_EOL . '$1.m1 = (float3){1.0f, 0.0f, 0.0f};' . PHP_EOL . '$1.m2 = (float3){0.0f, 1.0f, 0.0f};' . PHP_EOL . '$1.m3 = (float3){0.0f, 0.0f, 1.0f};'), // CRotationMatrix33 to matrix33 500 array('find' => "/swap\(($var),\s($var)\);/", 'replace' => '{ ' . $fod . ' temp = $1; $1 = $2; $2 = temp; }'),// swap vals 501 array('find' => "/($s|\()(-?\d+)f($s|;|\))/", 'replace' => '$1$2$3'), // int vals should not have a "f" at the end 502 // array('find' => "/sign\(($rval)\)$s\*$s($multChain)/", 'replace' => 'copysign($2, $1)'),// sign(x) * y => copysign(y, x) (this is wrong! probably copysign not usable at all) 503 504 // from here on its getting messy 505 //array('find' => "/1.0f$s\/$s($rval)/", 'replace' => 'native_recip($1)'), // native reciprocal 506 //array('find' => "/($rval)$s\/$s($rval)/", 'replace' => 'native_divide($1, $2)'), // native division 507 array('find' => "/($preF)native_recip\(native_sqrt($rval)\)/", 'replace' => '$1native_rsqrt$2'), // native reciprocal sqrt 508 //array('find' => "/($preF)native_sqrt\(native_recip($rval)\)/", 'replace' => '$1native_rsqrt$2'), // native reciprocal sqrt 509 510 // mad (literally ;D ) 511 //array('find' => "/\(($multChain)$s\*$s($rval)$s\+$s($multChain)\)/", 'replace' => '(mad($1, $2, $3))'), // (a * b + c) ====> mad(a, b, c) 512 //array('find' => "/\(($multChain)$s\*$s($rval)$s\-$s($multChain)\)/", 'replace' => '(mad($1, $2, -$3))'), // (a * b - c) ====> mad(a, b, -c) 513 //array('find' => "/([^*-]$s)($multChain)$s\*$s($rval)$s\+$s($multChain)(${'s'}[^*]|;)/", 'replace' => '$1mad($2, $3, $4)$5'), // a * b + c ====> mad(a, b, c) 514 //array('find' => "/([^*-]$s)($multChain)$s\*$s($rval)$s\-$s($multChain)(${'s'}[^*]|;)/", 'replace' => '$1mad($2, $3, -$4)$5'), // a * b - c ====> mad(a, b, -c) 515 //array('find' => "/\(($multChain)$s\+$s($rval)$s\*$s($multChain)\)/", 'replace' => '(mad($2, $3, $1))'), // (c + a * b) ====> mad(a, b, c) 516 //array('find' => "/\(($multChain)$s\-$s($rval)$s\*$s($multChain)\)/", 'replace' => '(mad(-$2, $3, $1))'), // (c - a * b) ====> mad(-a, b, c) 517 //array('find' => "/([^*-]$s)($multChain)$s\+$s($multChain)$s\*$s($rval)(${'s'}[^*]|;)/", 'replace' => '$1mad($4, $3, $2)$5'), // a * b + c ====> mad(a, b, c) 518 //array('find' => "/([^*-]$s)($multChain)$s\-$s($multChain)$s\*$s($rval)(${'s'}[^*]|;)/", 'replace' => '$1mad(-$4, $3, $2)$5'), // c - a * b ====> mad(-a, b, c) 519 520 // formula specific replacements 521 array('find' => "/^void(\s)/", 'replace' => $fod . '4 $1'), // mark void with inline void 522 array('find' => "/" . $fod . "4 &z/", 'replace' => $fod . '4 z'), // no passing by reference 523 //array('find' => "/" . $fod . " \&w/", 'replace' => $fod . ' *w'), // no passing by reference 524 //array('find' => "/z\./", 'replace' => 'z->'), 525 array('find' => "/" . $fod . "4 &z4D/", 'replace' => $fod . '4 *z4D'), // no passing by reference 526 array('find' => "/z4D\./", 'replace' => 'z4D->'), 527 array('find' => "/sExtendedAux &aux/", 'replace' => 'sExtendedAuxCl *aux'), // no passing by reference 528 array('find' => "/const sFractal \*fractal/", 'replace' => '__constant sFractalCl *fractal'), // no passing by reference 529 array('find' => "/aux\./", 'replace' => 'aux->'), 530 array('find' => "/const(\s\w+\s\*)/", 'replace' => '__constant$1'), // const modifier allowed for pointers (vars from outside) 531 array('find' => "/const(\s)/", 'replace' => '$1'), // const modifier not allowed for local vars 532 //array('find' => "/(\s)z\s=/", 'replace' => '$1*z ='), // z to pointer 533 //array('find' => "/(\s)z\s(.)=/", 'replace' => '$1*z $2='), // z to pointer 534 //array('find' => "/([\s\(-])z([,\);\s}])/", 'replace' => '$1*z$2'), // z to pointer 535 array('find' => "/(\s)z4D\s=/", 'replace' => '$1*z4D ='), // z4D to pointer 536 array('find' => "/(\s)z4D\s(.)=/", 'replace' => '$1*z4D $2='), // z4D to pointer 537 array('find' => "/([\s\(-])z4D([,\);\s}])/", 'replace' => '$1*z4D$2'), // z4D to pointer 538 //array('find' => "/(\s)w\s=/", 'replace' => '$1*w ='), // w to pointer 539 //array('find' => "/(\s)w\s(.)=/", 'replace' => '$1*w $2='), // w to pointer 540 //array('find' => "/([\s\(-])w([,\);\s}])/", 'replace' => '$1*w$2'), // w to pointer 541 array('find' => "/case ([a-zA-Z]+[a-zA-Z0-9_]+?[^l])(_[a-zA-Z0-9]+):/", 'replace' => 'case $1Cl$2:'), // replace enum switch cases with cl version 542 array('find' => "/== ([a-zA-Z]+[a-zA-Z0-9_]+?[^l])(_[a-zA-Z0-9]+)\)/", 'replace' => '== $1Cl$2)'), // replace enum if comparison with cl version 543 array('find' => "/($s)(enum[a-zA-Z0-9_]+?[^l])($s)/", 'replace' => '$1$2Cl$3'), // replace enum definitions with cl version 544 array('find' => "/M_PI([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'M_PI_F$1' : 'M_PI$1')), // replace Math constant 545 array('find' => "/M_PI_180([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'M_PI_180_F$1' : 'M_PI_180$1')), // replace Math constant 546 array('find' => "/M_PI_8([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'M_PI_8_F$1' : 'M_PI_8$1')), // replace Math constant 547 array('find' => "/M_PI_4([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'M_PI_4_F$1' : 'M_PI_4$1')), // replace Math constant 548 array('find' => "/M_PI_2x([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'M_PI_2x_F$1' : 'M_PI_2x$1')), // replace Math constant 549 array('find' => "/SQRT_1_3([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_1_3_F$1' : 'SQRT_1_3$1')), // replace Math constant 550 array('find' => "/SQRT_1_2([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_1_2_F$1' : 'SQRT_1_2$1')), // replace Math constant 551 array('find' => "/SQRT_2_3([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_2_3_F$1' : 'SQRT_2_3$1')), // replace Math constant 552 array('find' => "/SQRT_3_2([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_3_2_F$1' : 'SQRT_3_2$1')), // replace Math constant 553 array('find' => "/SQRT_3_4([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_3_4_F$1' : 'SQRT_3_4$1')), // replace Math constant 554 array('find' => "/SQRT_3_4d2([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_3_4d2_F$1' : 'SQRT_3_4d2$1')), // replace Math constant 555 array('find' => "/SQRT_3_4d2([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_3_4d2_F$1' : 'SQRT_3_4d2$1')), // replace Math constant 556 array('find' => "/SQRT_3([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'SQRT_3_F$1' : 'SQRT_3$1')), // replace Math constant 557 array('find' => "/FRAC_1_3([\s\)\};,])/", 'replace' => ($mode == 'single' ? 'FRAC_1_3_F$1' : 'FRAC_1_3$1')), // replace Math constant 558 559 560 array('find' => "/1e-061f/", 'replace' => ($mode == 'single' ? '1e-030f' : '1e-061')), // replace minimal double constant 561 array('find' => "/1e-021f/", 'replace' => ($mode == 'single' ? '1e-006f' : '1e-021')), // replace minimal double constant 562 array('find' => "/reinterpret_cast<(.*?)>\((.*?)\)/", 'replace' => '($1)$2'), // replace reinterpret_cast with simple cast 563 // TODO more replacements 564 ); 565 566 foreach ($cppToOpenCLReplaceLookup as $item) { 567 $code = preg_replace($item['find'], $item['replace'], $code); 568 $code = preg_replace($item['find'], $item['replace'], $code); // regex sometimes overlap, so run twice! 569 } 570 $code = substr($code, 0, -1) . 'return z;' . PHP_EOL . '}'; 571 return $code; 572} 573 574function generate_formula_icon($formula, $imgPath) 575{ 576 $formulaId = $formula['id']; 577 if ($formula['type'] == 'transf') { 578 $settings = '# Mandelbulber settings file 579# version 2.09 580# only modified parameters 581[main_parameters] 582ambient_occlusion_enabled true; 583camera 1,079630935663999 -2,590704819137228 1,163428502911517; 584camera_distance_to_target 7,000000000000004; 585camera_rotation 23,56505117707793 -24,60154959902026 0; 586camera_top -0,1664347300812756 0,3815883285622319 0,9092248501486611; 587flight_last_to_render 0; 588formula_1 7; 589formula_2 ' . $formulaId . '; 590hdr true; 591hybrid_fractal_enable true; 592image_height 256; 593image_width 256; 594keyframe_last_to_render 0; 595target -1,464862100002681 3,2431066939054 -1,750709177730066; 596[fractal_1] 597[fractal_2] 598info true; 599mandelbox_folding_limit -0,5; 600mandelbox_folding_value 0; 601transf_addition_constant_0000 0,1 -0,5 0,1 -0,2; 602transf_addition_constant_111 0,135135 1 1; 603transf_function_enabledAz_false true; 604transf_int_A 5; 605transf_int_B 5; 606transf_offset 0,7; 607transf_offset_0 0,8;'; 608 } else { 609 $settings = '# Mandelbulber settings file 610# version 2.09 611# only modified parameters 612[main_parameters] 613ambient_occlusion_enabled true; 614camera 1,080915186153033 -1,903722297292515 1,202015809937754; 615camera_distance_to_target 6,277124159763113; 616camera_rotation 29,9681686749304 -29,10022837829406 0; 617camera_top -0,2429354017345652 0,421316840960071 0,8737702845184721; 618DE_factor 0,18197; 619flight_last_to_render 0; 620formula_1 ' . $formulaId . '; 621hdr true; 622hybrid_fractal_enable true; 623image_height 256; 624image_width 256; 625keyframe_last_to_render 0; 626mat1_coloring_palette_offset 1,6; 627target -1,65882778581033 2,847745976777177 -1,850793618305075; 628[fractal_1] 629transf_function_enabled_false true; 630[fractal_2] 631info true; 632mandelbox_folding_limit -0,5; 633mandelbox_folding_value 0; 634transf_addition_constant 1,935484 0 0; 635transf_addition_constant_0000 0,1 -0,5 0,1 -0,2; 636transf_constant_multiplier_111 2,934272 2,089201 1,877934; 637transf_function_enabledy_false true; 638transf_function_enabledz_false true; 639transf_int_A 5; 640transf_int_B 5; 641transf_offset 0,7; 642transf_offset_0 0,8; 643transf_scale_0 0,034722; 644transf_scale_2 1,079812;'; 645 } 646 $tempFractPath = PROJECT_PATH . 'formula/img/' . $formula['internalName'] . '.fract'; 647 648 if (!file_exists($tempFractPath)) { // allow manual override 649 file_put_contents($tempFractPath, $settings); 650 } 651 if (!file_exists(MANDELBULBER_EXEC_PATH)) return false; 652 $cmd = MANDELBULBER_EXEC_PATH . " -n -f png16alpha -O 'opencl_enabled=0' -o '" . $imgPath . "' '" . $tempFractPath . "'"; 653 // echo PHP_EOL . $cmd . PHP_EOL; 654 shell_exec($cmd); 655 shell_exec("convert '" . $imgPath . "' -depth 8 '" . $imgPath . "'"); // save disk space with 8-bit png 656 return true; 657} 658 659function upgradeInternalName($internalName, $internalNameNew) 660{ 661 if (file_exists(PROJECT_PATH . 'formula/ui/' . $internalName . '.ui')) { 662 shell_exec('git mv' 663 . ' \'' . PROJECT_PATH . 'formula/ui/' . $internalName . '.ui\'' 664 . ' \'' . PROJECT_PATH . 'formula/ui/' . $internalNameNew . '.ui\'' 665 ); 666 } 667 if (file_exists(PROJECT_PATH . 'formula/img/' . $internalName . '.png')) { 668 shell_exec('git mv' 669 . ' \'' . PROJECT_PATH . 'formula/img/' . $internalName . '.png\'' 670 . ' \'' . PROJECT_PATH . 'formula/img/' . $internalNameNew . '.png\'' 671 ); 672 } 673 if (file_exists(PROJECT_PATH . 'formula/definition/fractal_' . $internalName . '.cpp')) { 674 shell_exec('git mv' 675 . ' \'' . PROJECT_PATH . 'formula/definition/fractal_' . $internalName . '.cpp\'' 676 . ' \'' . PROJECT_PATH . 'formula/definition/fractal_' . $internalNameNew . '.cpp\'' 677 ); 678 } 679 if (file_exists(PROJECT_PATH . 'formula/opencl/' . $internalName . '.cl')) { 680 shell_exec('git mv' 681 . ' \'' . PROJECT_PATH . 'formula/opencl/' . $internalName . '.cl\'' 682 . ' \'' . PROJECT_PATH . 'formula/opencl/' . $internalNameNew . '.cl\'' 683 ); 684 } 685 if (file_exists(PROJECT_PATH . 'formula/img/' . $internalName . '.fract')) { 686 shell_exec('git mv' 687 . ' \'' . PROJECT_PATH . 'formula/img/' . $internalName . '.fract\'' 688 . ' \'' . PROJECT_PATH . 'formula/img/' . $internalNameNew . '.fract\'' 689 ); 690 } 691 $fractal_list_content = file_get_contents(PROJECT_PATH . 'formula/definition/fractal_' . $internalNameNew . '.cpp'); 692 $fractal_list_content = str_replace('"' . $internalName . '"', '"' . $internalNameNew . '"', $fractal_list_content); 693 file_put_contents(PROJECT_PATH . 'formula/definition/fractal_' . $internalNameNew . '.cpp', $fractal_list_content); 694} 695 696function upgradeFunctionName($functionName, $functionNameNew) 697{ 698 $replaceInFiles = array( 699 PROJECT_PATH . 'src/compute_fractal.cpp', 700 PROJECT_PATH . 'src/fractal_formulas.cpp', 701 PROJECT_PATH . 'src/fractal_formulas.hpp', 702 PROJECT_PATH . 'src/fractal_list.cpp', 703 ); 704 foreach ($replaceInFiles as $replaceInFile) { 705 $fileContent = file_get_contents($replaceInFile); 706 $fileContent = str_replace($functionName, $functionNameNew, $fileContent); 707 file_put_contents($replaceInFile, $fileContent); 708 } 709} 710 711function from_camel_case($input) 712{ 713 $input = str_replace('dIFS', 'difs', $input); // explicitly keep those 714 preg_match_all('@([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)@', $input, $matches); 715 $ret = $matches[0]; 716 foreach ($ret as &$match) { 717 $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match); 718 } 719 return implode('_', $ret); 720} 721 722function writeFormulaCSV($formulas){ 723 $file = fopen(PROJECT_PATH . 'deploy/formulaData.csv', 'w'); 724 fputcsv($file, 725 array( 726 'index', 727 'name', 728 'deType', 729 'deFunctionType', 730 'pixelAddition', 731 'defaultBailout', 732 'analyticFunction', 733 'coloringFunction', 734 )); 735 foreach ($formulas as $index => $formula) { 736 $data = array( 737 $index, 738 $formula['nameInComboBox'], 739 // $formula['internalName'], 740 // $formula['functionName'], 741 $formula['DEType'], 742 $formula['DEFunctionType'], 743 $formula['cpixelAddition'], 744 $formula['defaultBailout'], 745 $formula['DEAnalyticFunction'], 746 $formula['coloringFunction'], 747 ); 748 749 fputcsv($file, $data); 750 } 751 fclose($file); 752} 753 754function writeParameterNamesTxt(){ 755 $fractalCpp = file_get_contents(PROJECT_PATH . 'src/fractal.cpp'); 756 preg_match_all('/(.*?)\s=[\s\n]+.*container->Get<(.*?)>\("(.*?)"(, i)?\).*;/', $fractalCpp, $matches); 757 $parameterNames = array(); 758 foreach($matches[0] as $i => $unused){ 759 $parameter = trim($matches[1][$i]); 760 if(strpos($parameter, '//') !== false) continue; // skip comments 761 $mainParameter = @explode('.', $parameter)[0]; 762 switch($matches[2][$i]){ 763 case 'double': $type = 'REAL'; break; 764 case 'CVector3': $type = 'REAL3'; break; 765 case 'CVector4': $type = 'REAL4'; break; 766 default: $type = $matches[2][$i]; 767 } 768 $name = $matches[3][$i]; 769 if(empty($matches[4][$i])){ 770 $parameterNames[$mainParameter][] = $parameter . ' ' . $type . ' ' . $name; 771 }else{ 772 if(strpos($parameter, 'mandelbox.rot') !== false){ 773 $minI = 1; 774 $maxI = 4; 775 } 776 if(strpos($parameter, 'IFS') !== false){ 777 $minI = 0; 778 $maxI = 9; 779 } 780 for($i = $minI; $i < $maxI; $i++){ 781 $parameterRun = $parameter; 782 $parameterRun = str_replace('[i - 1]', '[' . ($i - 1) . ']', $parameterRun); 783 $parameterRun = str_replace('[i]', '[' . $i . ']', $parameterRun); 784 $typeRun = str_replace('REAL3', 'matrix33', $type); 785 $parameterNames[$mainParameter][] = $parameterRun . ' ' . $typeRun . ' ' . $name . '_' . $i; 786 } 787 } 788 } 789 $txtFile = ''; 790 foreach($parameterNames as $parameterName => $parameterLines){ 791 $txtFile .= implode(PHP_EOL, $parameterLines) . PHP_EOL . PHP_EOL; 792 } 793 794 // derived parameters 795 preg_match_all('/(.*\..*?)\s=[\s\n]([A-Za-z0-9.+*\/\s\(\)]*);/', $fractalCpp, $matches); 796 foreach($matches[0] as $i => $line){ 797 if(strpos($line, '//') !== false || strpos($line, 'for (') !== false) continue; // skip comments and loops 798 $txtFile .= trim($matches[1][$i] . ' none none') . PHP_EOL; 799 800 } 801 802 $txtFile .= PHP_EOL; 803 $txtFile .= "IFS.mainRot matrix33 IFS_rotation" . PHP_EOL; 804 $txtFile .= "mandelbox.mainRot matrix33 mandelbox_rotation_main" . PHP_EOL; 805 $txtFile .= "transformCommon.rotationMatrix matrix33 transf_rotation" . PHP_EOL; 806 $txtFile .= "transformCommon.rotationMatrix2 matrix33 transf_rotation2" . PHP_EOL; 807 808 file_put_contents(PROJECT_PATH . 'deploy/share/mandelbulber2/data/parameterNames.txt', $txtFile); 809} 810 811function writeFractalDefinitionFile($formulas){ 812 $out = '/** 813 * Mandelbulber v2, a 3D fractal generator _%}}i*<. ______ 814 * Copyright (C) ' . date('Y') . ' Mandelbulber Team _>]|=||i=i<, / ____/ __ __ 815 * \><||i|=>>%) / / __/ /___/ /_ 816 * This file is part of Mandelbulber. )<=i=]=|=i<> / /__ /_ __/_ __/ 817 * The project is licensed under GPLv3, -<>>=|><|||` \____/ /_/ /_/ 818 * see also COPYING file in this folder. ~+{i%+++ 819 */ 820 821#ifndef MANDELBULBER2_FORMULA_DEFINITION_ALL_FRACTAL_DEFINITIONS_H_ 822#define MANDELBULBER2_FORMULA_DEFINITION_ALL_FRACTAL_DEFINITIONS_H_ 823 824#include "abstract_fractal.h" 825 826'; 827 $out .= 'FRACTAL_CLASS(cFractalNone)' . PHP_EOL; 828 foreach ($formulas as $index => $formula) { 829 830 $out .= 'FRACTAL_CLASS(cFractal' . ucfirst($index) . ')' . PHP_EOL; 831 } 832 $out .= ' 833#endif /* MANDELBULBER2_FORMULA_DEFINITION_ALL_FRACTAL_DEFINITIONS_H_ */ 834'; 835 file_put_contents(PROJECT_PATH . 'formula/definition/all_fractal_definitions.h', $out); 836 837 /* 838 $out = '//====================== FRACTAL LIST - START ==================' . PHP_EOL; 839 foreach ($formulas as $index => $formula) { 840 $out .= ' newFractalList.append(new cFractal' . ucfirst($index) . '());' . PHP_EOL; 841 } 842 $out .= ' //====================== FRACTAL LIST - END =================='; 843 */ 844 $regex = '/\/\/=* FRACTAL LIST - START =*[\s\S]*?\/\/=* FRACTAL LIST - END =*/'; 845 /* 846 file_put_contents(PROJECT_PATH . 'formula/definition/all_fractal_list.cpp', preg_replace($regex, $out, file_get_contents(PROJECT_PATH . 'src/fractal_list.cpp'))); 847 */ 848} 849 850?> 851 852