├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .postcssrc.js
├── LICENSE
├── README.md
├── Screenshot
└── a.jpg
├── build
├── build.js
├── check-versions.js
├── logo.png
├── utils.js
├── vue-loader.conf.js
├── webpack.base.conf.js
├── webpack.dev.conf.js
└── webpack.prod.conf.js
├── config
├── dev.env.js
├── index.js
├── prod.env.js
└── test.env.js
├── index.html
├── package-lock.json
├── package.json
├── src
├── Produce.vue
├── assets
│ ├── attributes-tabs.css
│ ├── core
│ │ ├── icons.css
│ │ └── icons
│ │ │ ├── eye.gif
│ │ │ ├── geometry.gif
│ │ │ ├── image.gif
│ │ │ ├── light.gif
│ │ │ ├── material.gif
│ │ │ ├── mesh.gif
│ │ │ ├── model.gif
│ │ │ ├── node.gif
│ │ │ └── scene.gif
│ ├── fonts
│ │ └── fontawesome-webfont.woff2
│ ├── logo.png
│ ├── materialDefs
│ │ ├── GizmoDef
│ │ └── HelperUnlitDef
│ ├── materialdefs
│ │ └── HelperMaterialDef
│ ├── shadernodes
│ │ ├── controls.css
│ │ ├── index.sass
│ │ └── shadernodes.css
│ ├── textures
│ │ └── lightbulb32.png
│ └── tools.css
├── components
│ ├── Attributes.vue
│ ├── HelloWorld.vue
│ ├── LeadingPrinciples.vue
│ ├── Port.vue
│ ├── ShaderNode.vue
│ ├── ShadingEdit.vue
│ ├── Viewer.vue
│ ├── attributes
│ │ ├── AttrItem.vue
│ │ ├── material
│ │ │ └── MaterialProperty.vue
│ │ ├── object
│ │ │ ├── OBJ_Geometry.vue
│ │ │ ├── OBJ_Light.vue
│ │ │ ├── OBJ_Node.vue
│ │ │ └── OBJ_None.vue
│ │ └── renderer
│ │ │ └── RendererProperty.vue
│ ├── common
│ │ ├── BoolComponent.vue
│ │ ├── BoolGroupComponent.vue
│ │ ├── ColorComponent.vue
│ │ ├── CombinationComponent.vue
│ │ ├── ImgComponent.vue
│ │ ├── NumberComponent.vue
│ │ ├── SelectComponent.vue
│ │ ├── TransformComponent.vue
│ │ ├── VectorColorComponent.vue
│ │ └── VectorComponent.vue
│ ├── shadernodes
│ │ ├── common
│ │ │ ├── Color.vue
│ │ │ └── TextInput.vue
│ │ └── math
│ │ │ └── Number.vue
│ └── ui
│ │ ├── ContextMenu.vue
│ │ └── Tree.vue
├── editor
│ ├── Arrow.js
│ ├── EditorContext.js
│ ├── GlobalConfig.js
│ ├── attributes
│ │ └── object
│ │ │ └── ObjNode.js
│ ├── command
│ │ ├── BaseCommand.js
│ │ ├── CommandFactory.js
│ │ └── CommandManager.js
│ ├── common
│ │ ├── LightFactory.js
│ │ ├── Material.js
│ │ ├── PostFilterFactory.js
│ │ └── ShapeFactory.js
│ ├── leadingPrinciples
│ │ └── LeadingPrinciples.js
│ ├── shadernodes
│ │ ├── MaterialDefFactory.js
│ │ ├── ShaderNode.js
│ │ ├── ShaderNodes.js
│ │ ├── Sockets.js
│ │ ├── common
│ │ │ ├── Commons.js
│ │ │ ├── IfElseBranchComponent.js
│ │ │ └── TransformVector3Component.js
│ │ ├── input
│ │ │ ├── BoolInputStructureComponent.js
│ │ │ ├── FloatInputStructureComponent.js
│ │ │ ├── InputAttributeComponent.js
│ │ │ ├── InputMatrixComponent.js
│ │ │ ├── InputStructureComponent.js
│ │ │ ├── Inputs.js
│ │ │ ├── IntInputStructureComponent.js
│ │ │ ├── Vec2InputStructureComponent.js
│ │ │ ├── Vec3InputStructureComponent.js
│ │ │ └── Vec4InputStructureComponent.js
│ │ ├── math
│ │ │ ├── AddComponent.js
│ │ │ ├── ConstructVec2Component.js
│ │ │ ├── ConstructVec3Component.js
│ │ │ ├── ConstructVec4Component.js
│ │ │ ├── DivideComponent.js
│ │ │ ├── MathComponent.js
│ │ │ ├── Maths.js
│ │ │ ├── MultiplyComponent.js
│ │ │ ├── NumberComponent.js
│ │ │ ├── NumberControl.js
│ │ │ ├── SubtractComponent.js
│ │ │ └── Vec2Splitter.js
│ │ ├── output
│ │ │ ├── BoolOutputStructureComponent.js
│ │ │ ├── FloatOutputStructureComponent.js
│ │ │ ├── FragmentShaderOutComponent.js
│ │ │ ├── IntOutputStructureComponent.js
│ │ │ ├── OutputStructureComponent.js
│ │ │ ├── Outputs.js
│ │ │ ├── Vec2OutputStructureComponent.js
│ │ │ ├── Vec3OutputStructureComponent.js
│ │ │ ├── Vec4OutputStructureComponent.js
│ │ │ └── VertexShaderOutComponent.js
│ │ ├── param
│ │ │ ├── BoolParamComponent.js
│ │ │ ├── FloatParamComponent.js
│ │ │ ├── IntParamComponent.js
│ │ │ ├── ParamComponent.js
│ │ │ ├── Params.js
│ │ │ ├── TextControl.js
│ │ │ ├── Texture2DParamComponent.js
│ │ │ ├── TextureCubeParamComponent.js
│ │ │ ├── Vec2ParamComponent.js
│ │ │ ├── Vec3ParamComponent.js
│ │ │ └── Vec4ParamComponent.js
│ │ └── texture
│ │ │ ├── ColorControl.js
│ │ │ ├── SamplerTexture2DComponent.js
│ │ │ └── Textures.js
│ ├── utils
│ │ ├── ColorMath.js
│ │ ├── ObjControl.js
│ │ └── Utils.js
│ └── viewer
│ │ └── Viewer.js
├── main.js
└── router
│ ├── index.js
│ └── produce.js
├── static
├── .gitkeep
├── MaterialDefinitionSource.html
└── heighlight
│ ├── default.min.css
│ ├── glsl.min.js
│ └── highlight.min.js
├── test.html
├── test.txt
└── test
├── e2e
├── custom-assertions
│ └── elementCount.js
├── nightwatch.conf.js
├── runner.js
└── specs
│ └── test.js
└── unit
├── .eslintrc
├── jest.conf.js
├── setup.js
└── specs
└── HelloWorld.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 | /test/unit/coverage/
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | extends: [
12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14 | 'plugin:vue/essential',
15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16 | 'standard'
17 | ],
18 | // required to lint *.vue files
19 | plugins: [
20 | 'vue'
21 | ],
22 | // add your custom rules here
23 | rules: {
24 | // allow async-await
25 | 'generator-star-spacing': 'off',
26 | // allow debugger during development
27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/unit/coverage/
8 | /test/e2e/reports/
9 | selenium-debug.log
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # produce
2 |
3 | > Lightweight 3D editor on the web,It uses [Try3d.Js](https://github.com/JohnLKkk/try3d.git) I wrote as renderer.
4 |
5 | 
6 | ## Build Setup
7 |
8 | ``` bash
9 | clone project
10 | # serve with hot reload at localhost:8080
11 | npm run dev
12 | ```
13 |
14 | For questions, please contact me:
15 | email:18402012144@163.com
16 | wechat:18402012144
17 |
--------------------------------------------------------------------------------
/Screenshot/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/Screenshot/a.jpg
--------------------------------------------------------------------------------
/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/build/logo.png
--------------------------------------------------------------------------------
/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | const createLintingRule = () => ({
12 | test: /\.(js|vue)$/,
13 | loader: 'eslint-loader',
14 | enforce: 'pre',
15 | include: [resolve('src'), resolve('test')],
16 | options: {
17 | formatter: require('eslint-friendly-formatter'),
18 | emitWarning: !config.dev.showEslintErrorsInOverlay
19 | }
20 | })
21 |
22 | module.exports = {
23 | context: path.resolve(__dirname, '../'),
24 | entry: {
25 | app: './src/main.js'
26 | },
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: '[name].js',
30 | publicPath: process.env.NODE_ENV === 'production'
31 | ? config.build.assetsPublicPath
32 | : config.dev.assetsPublicPath
33 | },
34 | resolve: {
35 | extensions: ['.js', '.vue', '.json'],
36 | alias: {
37 | 'vue$': 'vue/dist/vue.esm.js',
38 | '@': resolve('src'),
39 | }
40 | },
41 | module: {
42 | rules: [
43 | // ...(config.dev.useEslint ? [createLintingRule()] : []),
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue-loader',
47 | options: vueLoaderConfig
48 | },
49 | {
50 | test: /\.js$/,
51 | loader: 'babel-loader',
52 | include: [resolve('src'), resolve('test'), resolve('node_modules/try3d/src'), resolve('node_modules/webpack-dev-server/client')]
53 | },
54 | {
55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56 | loader: 'url-loader',
57 | options: {
58 | limit: 10000,
59 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
60 | }
61 | },
62 | {
63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64 | loader: 'url-loader',
65 | options: {
66 | limit: 10000,
67 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
68 | }
69 | },
70 | {
71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76 | }
77 | }
78 | ]
79 | },
80 | node: {
81 | // prevent webpack from injecting useless setImmediate polyfill because Vue
82 | // source contains it (although only uses it if it's native).
83 | setImmediate: false,
84 | // prevent webpack from injecting mocks to Node native modules
85 | // that does not make sense for the client
86 | dgram: 'empty',
87 | fs: 'empty',
88 | net: 'empty',
89 | tls: 'empty',
90 | child_process: 'empty'
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = process.env.NODE_ENV === 'testing'
15 | ? require('../config/test.env')
16 | : require('../config/prod.env')
17 |
18 | const webpackConfig = merge(baseWebpackConfig, {
19 | module: {
20 | rules: utils.styleLoaders({
21 | sourceMap: config.build.productionSourceMap,
22 | extract: true,
23 | usePostCSS: true
24 | })
25 | },
26 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
30 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
31 | },
32 | plugins: [
33 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
34 | new webpack.DefinePlugin({
35 | 'process.env': env
36 | }),
37 | new UglifyJsPlugin({
38 | uglifyOptions: {
39 | compress: {
40 | warnings: false
41 | }
42 | },
43 | sourceMap: config.build.productionSourceMap,
44 | parallel: true
45 | }),
46 | // extract css into its own file
47 | new ExtractTextPlugin({
48 | filename: utils.assetsPath('css/[name].[contenthash].css'),
49 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
50 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
51 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
52 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
53 | allChunks: true,
54 | }),
55 | // Compress extracted CSS. We are using this plugin so that possible
56 | // duplicated CSS from different components can be deduped.
57 | new OptimizeCSSPlugin({
58 | cssProcessorOptions: config.build.productionSourceMap
59 | ? { safe: true, map: { inline: false } }
60 | : { safe: true }
61 | }),
62 | // generate dist index.html with correct asset hash for caching.
63 | // you can customize output by editing /index.html
64 | // see https://github.com/ampedandwired/html-webpack-plugin
65 | new HtmlWebpackPlugin({
66 | filename: process.env.NODE_ENV === 'testing'
67 | ? 'index.html'
68 | : config.build.index,
69 | template: 'index.html',
70 | inject: true,
71 | minify: {
72 | removeComments: true,
73 | collapseWhitespace: true,
74 | removeAttributeQuotes: true
75 | // more options:
76 | // https://github.com/kangax/html-minifier#options-quick-reference
77 | },
78 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
79 | chunksSortMode: 'dependency'
80 | }),
81 | // keep module.id stable when vendor modules does not change
82 | new webpack.HashedModuleIdsPlugin(),
83 | // enable scope hoisting
84 | new webpack.optimize.ModuleConcatenationPlugin(),
85 | // split vendor js into its own file
86 | new webpack.optimize.CommonsChunkPlugin({
87 | name: 'vendor',
88 | minChunks (module) {
89 | // any required modules inside node_modules are extracted to vendor
90 | return (
91 | module.resource &&
92 | /\.js$/.test(module.resource) &&
93 | module.resource.indexOf(
94 | path.join(__dirname, '../node_modules')
95 | ) === 0
96 | )
97 | }
98 | }),
99 | // extract webpack runtime and module manifest to its own file in order to
100 | // prevent vendor hash from being updated whenever app bundle is updated
101 | new webpack.optimize.CommonsChunkPlugin({
102 | name: 'manifest',
103 | minChunks: Infinity
104 | }),
105 | // This instance extracts shared chunks from code splitted chunks and bundles them
106 | // in a separate chunk, similar to the vendor chunk
107 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
108 | new webpack.optimize.CommonsChunkPlugin({
109 | name: 'app',
110 | async: 'vendor-async',
111 | children: true,
112 | minChunks: 3
113 | }),
114 |
115 | // copy custom static assets
116 | new CopyWebpackPlugin([
117 | {
118 | from: path.resolve(__dirname, '../static'),
119 | to: config.build.assetsSubDirectory,
120 | ignore: ['.*']
121 | }
122 | ])
123 | ]
124 | })
125 |
126 | if (config.build.productionGzip) {
127 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
128 |
129 | webpackConfig.plugins.push(
130 | new CompressionWebpackPlugin({
131 | asset: '[path].gz[query]',
132 | algorithm: 'gzip',
133 | test: new RegExp(
134 | '\\.(' +
135 | config.build.productionGzipExtensions.join('|') +
136 | ')$'
137 | ),
138 | threshold: 10240,
139 | minRatio: 0.8
140 | })
141 | )
142 | }
143 |
144 | if (config.build.bundleAnalyzerReport) {
145 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
146 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
147 | }
148 |
149 | module.exports = webpackConfig
150 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 | // Use Eslint Loader?
24 | // If true, your code will be linted during bundling and
25 | // linting errors and warnings will be shown in the console.
26 | useEslint: true,
27 | // If true, eslint errors and warnings will also be shown in the error overlay
28 | // in the browser.
29 | showEslintErrorsInOverlay: false,
30 |
31 | /**
32 | * Source Maps
33 | */
34 |
35 | // https://webpack.js.org/configuration/devtool/#development
36 | devtool: 'cheap-module-eval-source-map',
37 |
38 | // If you have problems debugging vue-files in devtools,
39 | // set this to false - it *may* help
40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
41 | cacheBusting: true,
42 |
43 | cssSourceMap: true
44 | },
45 |
46 | build: {
47 | // Template for index.html
48 | index: path.resolve(__dirname, '../dist/index.html'),
49 |
50 | // Paths
51 | assetsRoot: path.resolve(__dirname, '../dist'),
52 | assetsSubDirectory: 'static',
53 | assetsPublicPath: '/',
54 |
55 | /**
56 | * Source Maps
57 | */
58 |
59 | productionSourceMap: true,
60 | // https://webpack.js.org/configuration/devtool/#production
61 | devtool: '#source-map',
62 |
63 | // Gzip off by default as many popular static hosts such as
64 | // Surge or Netlify already gzip all static assets for you.
65 | // Before setting to `true`, make sure to:
66 | // npm install --save-dev compression-webpack-plugin
67 | productionGzip: false,
68 | productionGzipExtensions: ['js', 'css'],
69 |
70 | // Run the build command with an extra argument to
71 | // View the bundle analyzer report after build finishes:
72 | // `npm run build --report`
73 | // Set to `true` or `false` to always turn it on or off
74 | bundleAnalyzerReport: process.env.npm_config_report
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const devEnv = require('./dev.env')
4 |
5 | module.exports = merge(devEnv, {
6 | NODE_ENV: '"testing"'
7 | })
8 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | produce
7 |
8 |
9 |
10 |
11 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "produce",
3 | "version": "1.0.0",
4 | "description": "Effects editor on the web ",
5 | "author": "JhonKkk <1724624287@qq.com>",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "unit": "jest --config test/unit/jest.conf.js --coverage",
11 | "e2e": "node test/e2e/runner.js",
12 | "test": "npm run unit && npm run e2e",
13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
14 | "build": "node build/build.js"
15 | },
16 | "dependencies": {
17 | "@babel/polyfill": "^7.12.1",
18 | "@hscmap/vue-menu": "^2.10.1",
19 | "element": "^0.1.4",
20 | "element-resize-detector": "^1.2.4",
21 | "rete": "^1.2.2",
22 | "rete-area-plugin": "^0.2.1",
23 | "rete-connection-plugin": "^0.2.2",
24 | "rete-context-menu-plugin": "^0.5.2",
25 | "rete-history-plugin": "^0.2.2",
26 | "rete-task-plugin": "^0.2.2",
27 | "rete-vue-render-plugin": "^0.2.2",
28 | "splitpanes": "^2.3.8",
29 | "vcolorpicker": "^1.1.0",
30 | "vue": "^2.5.2",
31 | "vue-contextmenu": "^1.5.11",
32 | "vue-dialog-drag": "^0.1.29",
33 | "vue-drag-resize": "^1.5.4",
34 | "vue-jstree": "^2.1.6",
35 | "vue-nav-tabs": "^0.5.7",
36 | "vue-router": "^3.0.1"
37 | },
38 | "devDependencies": {
39 | "autoprefixer": "^7.1.2",
40 | "babel-core": "^6.22.1",
41 | "babel-eslint": "^8.2.1",
42 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
43 | "babel-jest": "^21.0.2",
44 | "babel-loader": "^7.1.1",
45 | "babel-plugin-dynamic-import-node": "^1.2.0",
46 | "babel-plugin-syntax-jsx": "^6.18.0",
47 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
48 | "babel-plugin-transform-runtime": "^6.22.0",
49 | "babel-plugin-transform-vue-jsx": "^3.5.0",
50 | "babel-preset-env": "^1.3.2",
51 | "babel-preset-stage-2": "^6.22.0",
52 | "babel-register": "^6.22.0",
53 | "chalk": "^2.0.1",
54 | "chromedriver": "^2.27.2",
55 | "copy-webpack-plugin": "^4.0.1",
56 | "cross-spawn": "^5.0.1",
57 | "css-loader": "^0.28.0",
58 | "eslint": "^4.15.0",
59 | "eslint-config-standard": "^10.2.1",
60 | "eslint-friendly-formatter": "^3.0.0",
61 | "eslint-loader": "^1.7.1",
62 | "eslint-plugin-import": "^2.7.0",
63 | "eslint-plugin-node": "^5.2.0",
64 | "eslint-plugin-promise": "^3.4.0",
65 | "eslint-plugin-standard": "^3.0.1",
66 | "eslint-plugin-vue": "^4.0.0",
67 | "extract-text-webpack-plugin": "^3.0.0",
68 | "file-loader": "^1.1.4",
69 | "friendly-errors-webpack-plugin": "^1.6.1",
70 | "html-webpack-plugin": "^2.30.1",
71 | "jest": "^22.0.4",
72 | "jest-serializer-vue": "^0.3.0",
73 | "nightwatch": "^0.9.12",
74 | "node-notifier": "^5.1.2",
75 | "optimize-css-assets-webpack-plugin": "^3.2.0",
76 | "ora": "^1.2.0",
77 | "portfinder": "^1.0.13",
78 | "postcss-import": "^11.0.0",
79 | "postcss-loader": "^2.0.8",
80 | "postcss-url": "^7.2.1",
81 | "rimraf": "^2.6.0",
82 | "selenium-server": "^3.0.1",
83 | "semver": "^5.3.0",
84 | "shelljs": "^0.7.6",
85 | "try3d": "^0.4.3",
86 | "uglifyjs-webpack-plugin": "^1.1.1",
87 | "url-loader": "^0.5.8",
88 | "vue-jest": "^1.0.2",
89 | "vue-loader": "^13.3.0",
90 | "vue-style-loader": "^3.0.1",
91 | "vue-template-compiler": "^2.5.2",
92 | "webpack": "^3.6.0",
93 | "webpack-bundle-analyzer": "^2.9.0",
94 | "webpack-dev-server": "^2.9.1",
95 | "webpack-merge": "^4.1.0"
96 | },
97 | "engines": {
98 | "node": ">= 6.0.0",
99 | "npm": ">= 3.0.0"
100 | },
101 | "browserslist": [
102 | "> 1%",
103 | "last 2 versions",
104 | "not ie <= 8"
105 | ]
106 | }
107 |
--------------------------------------------------------------------------------
/src/Produce.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
42 |
43 |
54 |
--------------------------------------------------------------------------------
/src/assets/attributes-tabs.css:
--------------------------------------------------------------------------------
1 | .vue-tabs.stacked {
2 | display: flex; }
3 |
4 | .vue-tabs .tabs__link {
5 | text-decoration: none;
6 | color: gray; }
7 |
8 | .vue-tabs .nav {
9 | margin-bottom: 0;
10 | margin-top: 0;
11 | padding-left: 0;
12 | list-style: none; }
13 | .vue-tabs .nav:before, .vue-tabs .nav:after {
14 | content: " ";
15 | display: table; }
16 | .vue-tabs .nav:after {
17 | clear: both; }
18 | .vue-tabs .nav > li {
19 | position: relative;
20 | display: block; }
21 | .vue-tabs .nav > li > a {
22 | position: relative;
23 | display: block;
24 | margin: 5px 0px 5px 5px;
25 | padding: 5px; }
26 | .vue-tabs .nav > li > a:hover, .vue-tabs .nav > li > a:focus {
27 | text-decoration: none;
28 | background-color: #282828; }
29 | .vue-tabs .nav > li span.title {
30 | display: flex;
31 | justify-content: center; }
32 | .vue-tabs .nav > li.disabled > a {
33 | color: #777777; }
34 | .vue-tabs .nav > li.disabled > a:hover, .vue-tabs .nav > li.disabled > a:focus {
35 | color: #777777;
36 | text-decoration: none;
37 | cursor: not-allowed;
38 | background-color: transparent;
39 | border-color: transparent; }
40 | .vue-tabs .nav .nav-divider {
41 | height: 1px;
42 | margin: 9px 0;
43 | overflow: hidden;
44 | background-color: #e5e5e5; }
45 | .vue-tabs .nav > li > a > img {
46 | max-width: none; }
47 |
48 | .vue-tabs .nav-tabs {
49 | border-bottom: 1px solid #ddd; }
50 | .vue-tabs .nav-tabs > li {
51 | float: left;
52 | margin-bottom: -1px; }
53 | .vue-tabs .nav-tabs > li > a {
54 | margin-right: 2px;
55 | line-height: 1.42857;
56 | border: 1px solid transparent;
57 | border-radius: 4px 4px 0 0; }
58 | .vue-tabs .nav-tabs > li > a:hover {
59 | border-color: #eeeeee #eeeeee #ddd; }
60 | .vue-tabs .nav-tabs > li.active > a, .vue-tabs .nav-tabs > li.active > a:hover, .vue-tabs .nav-tabs > li.active > a:focus {
61 | color: #555555;
62 | background-color: #fff;
63 | border: 1px solid #ddd;
64 | border-bottom-color: transparent;
65 | cursor: default; }
66 |
67 | .vue-tabs .nav-pills > li {
68 | float: left; }
69 | .vue-tabs .nav-pills > li > a {
70 | border-radius: 4px 0px 0px 4px; }
71 | .vue-tabs .nav-pills > li + li {
72 | margin-left: 2px; }
73 | .vue-tabs .nav-pills > li.active > a, .vue-tabs .nav-pills > li.active > a:hover, .vue-tabs .nav-pills > li.active > a:focus {
74 | color: #fff;
75 | background-color: #337ab7; }
76 |
77 | .vue-tabs .nav-stacked > li {
78 | float: none; }
79 | .vue-tabs .nav-stacked > li + li {
80 | margin-top: 2px;
81 | margin-left: 0; }
82 |
83 | .vue-tabs .nav-justified, .vue-tabs .nav-tabs.nav-justified {
84 | width: 100%; }
85 | .vue-tabs .nav-justified > li, .vue-tabs .nav-tabs.nav-justified > li {
86 | float: none; }
87 | .vue-tabs .nav-justified > li > a, .vue-tabs .nav-tabs.nav-justified > li > a {
88 | text-align: center;
89 | margin-bottom: 5px; }
90 | .vue-tabs .nav-justified > .dropdown .dropdown-menu {
91 | top: auto;
92 | left: auto; }
93 | @media (min-width: 768px) {
94 | .vue-tabs .nav-justified > li, .vue-tabs .nav-tabs.nav-justified > li {
95 | display: table-cell;
96 | width: 1%; }
97 | .vue-tabs .nav-justified > li > a, .vue-tabs .nav-tabs.nav-justified > li > a {
98 | margin-bottom: 0; } }
99 |
100 | .vue-tabs .nav-tabs-justified, .vue-tabs .nav-tabs.nav-justified {
101 | border-bottom: 0; }
102 | .vue-tabs .nav-tabs-justified > li > a, .vue-tabs .nav-tabs.nav-justified > li > a {
103 | margin-right: 0;
104 | border-radius: 4px; }
105 | .vue-tabs .nav-tabs-justified > .active > a, .vue-tabs .nav-tabs.nav-justified > .active > a,
106 | .vue-tabs .nav-tabs-justified > .active > a:hover, .vue-tabs .nav-tabs.nav-justified > .active > a:hover,
107 | .vue-tabs .nav-tabs-justified > .active > a:focus, .vue-tabs .nav-tabs.nav-justified > .active > a:focus {
108 | border: 1px solid #ddd; }
109 | @media (min-width: 768px) {
110 | .vue-tabs .nav-tabs-justified > li > a, .vue-tabs .nav-tabs.nav-justified > li > a {
111 | border-bottom: 1px solid #ddd;
112 | border-radius: 4px 4px 0 0; }
113 | .vue-tabs .nav-tabs-justified > .active > a, .vue-tabs .nav-tabs.nav-justified > .active > a,
114 | .vue-tabs .nav-tabs-justified > .active > a:hover, .vue-tabs .nav-tabs.nav-justified > .active > a:hover,
115 | .vue-tabs .nav-tabs-justified > .active > a:focus, .vue-tabs .nav-tabs.nav-justified > .active > a:focus {
116 | border-bottom-color: #fff; } }
117 |
118 | .vue-tabs .tab-content > .tab-pane {
119 | display: none; }
120 |
121 | .vue-tabs .tab-content > .active {
122 | display: block; }
123 |
124 | .vue-tabs section[aria-hidden="true"] {
125 | display: none; }
126 | .right-text-tabs{
127 | min-width: 100%;
128 | min-height: 100%;
129 | }
130 |
--------------------------------------------------------------------------------
/src/assets/core/icons/eye.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/eye.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/geometry.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/geometry.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/image.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/image.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/light.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/light.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/material.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/material.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/mesh.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/mesh.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/model.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/model.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/node.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/node.gif
--------------------------------------------------------------------------------
/src/assets/core/icons/scene.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/core/icons/scene.gif
--------------------------------------------------------------------------------
/src/assets/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/materialDefs/GizmoDef:
--------------------------------------------------------------------------------
1 | // 用于3D视图编辑器中的ObjControl操作
2 | Def GizmoDef{
3 | Params{
4 | vec4 color;
5 | vec4 highlightColor;
6 | sampler2D colorMap;
7 | float alphaDiscard;
8 | }
9 | SubTechnology NormPass{
10 | Vars{
11 | vec4 wordPosition;
12 | vec2 uv0;
13 | }
14 | Vs_Shader{
15 | void main(){
16 | Context.OutPosition = Context.ProjectMatrix * Context.ViewMatrix * Context.ModelMatrix * vec4(Context.InPosition, 1.0f);
17 | uv0 = Context.InUv0;
18 | }
19 | }
20 | Fs_Shader{
21 | void main(){
22 | Context.OutColor = vec4(1.0f);
23 | // 使用自定义颜色输出
24 | #ifdef Params.color
25 | Context.OutColor *= Params.color;
26 | #endif
27 | #ifdef Params.colorMap
28 | Context.OutColor *= texture(Params.colorMap, uv0);
29 | #endif
30 | #ifdef Params.alphaDiscard
31 | if(Context.OutColor.a < Params.alphaDiscard){
32 | discard;
33 | }
34 | #endif
35 | // 高亮
36 | #ifdef Params.highlightColor
37 | Context.OutColor = mix(Context.OutColor, Params.highlightColor, 0.85f);
38 | #endif
39 | }
40 | }
41 | }
42 | Technology{
43 | Sub_Pass{
44 | Pass NormPass{
45 | DepthTest Off;
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/assets/materialDefs/HelperUnlitDef:
--------------------------------------------------------------------------------
1 | // 颜色材质,提供指定颜色或颜色纹理并渲染
2 | Def HelperUnlitDef{
3 | Params{
4 | vec4 color;
5 | sampler2D colorMap;
6 | float alphaDiscard;
7 | }
8 | SubTechnology ColorPass{
9 | Vars{
10 | vec4 wordPosition;
11 | vec2 uv0;
12 | }
13 | Vs_Shader{
14 | void main(){
15 | //Context.OutPosition = Context.ProjectViewModelMatrix * vec4(Context.InPosition, 1.0f);
16 | Context.OutPosition = Context.ProjectMatrix * Context.ViewMatrix * Context.ModelMatrix * vec4(Context.InPosition, 1.0f);
17 | wordPosition = Context.OutPosition;
18 | uv0 = Context.InUv0;
19 | }
20 | }
21 | Fs_Shader{
22 | void main(){
23 | Context.OutColor = vec4(1.0f);
24 | // 使用自定义颜色输出
25 | #ifdef Params.color
26 | Context.OutColor *= Params.color;
27 | #endif
28 |
29 | // 使用纹理
30 | #ifdef Params.colorMap
31 | Context.OutColor *= texture(Params.colorMap, uv0);
32 | #endif
33 |
34 | #ifdef Params.alphaDiscard
35 | if(Context.OutColor.a < Params.alphaDiscard){
36 | discard;
37 | }
38 | #endif
39 | }
40 | }
41 | }
42 | Technology{
43 | Sub_Pass{
44 | Pass ColorPass{
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/assets/materialdefs/HelperMaterialDef:
--------------------------------------------------------------------------------
1 | // 用于编辑器辅助工具材质定义
2 | Def HelperMaterialDef{
3 | Params{
4 | vec4 color;
5 | sampler2D colorMap;
6 | float alphaDiscard;
7 | }
8 | SubTechnology ScalePass{
9 | Vars{
10 | vec4 wordPosition;
11 | }
12 | Vs_Shader{
13 | void main(){
14 | //Context.OutPosition = Context.ProjectViewModelMatrix * vec4(Context.InPosition, 1.0f);
15 | mat4 scaleMat4 = mat4(
16 | 0.2f, 0.0f, 0.0f, 0.0f,
17 | 0.0f, 0.2f, 0.0f, 0.0f,
18 | 0.0f, 0.0f, 0.2f, 0.0f,
19 | 0.0f, 0.0f, 0.0f, 1.0f
20 | );
21 | Context.OutPosition = Context.ProjectMatrix * Context.ViewMatrix * Context.ModelMatrix * vec4(Context.InPosition, 1.0f);
22 | wordPosition = Context.OutPosition;
23 | }
24 | }
25 | Fs_Shader{
26 | void main(){
27 | // 使用自定义颜色输出
28 | #ifdef Params.color
29 | Context.OutColor = Params.color;
30 | #else
31 | // 使用纹理
32 | #ifdef Params.colorMap
33 | Context.OutColor = texture(Params.colorMap, Context.InUv0);
34 | #ifdef Params.alphaDiscard
35 | if(Context.OutColor.a < Params.alphaDiscard){
36 | discard;
37 | }
38 | #endif
39 | #else
40 | Context.OutColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);
41 | #endif
42 | #endif
43 | vec4 wPosition = wordPosition;
44 | }
45 | }
46 | }
47 | SubTechnology ColorPass{
48 | Vars{
49 | vec4 wordPosition;
50 | vec2 uv0;
51 | }
52 | Vs_Shader{
53 | void main(){
54 | //Context.OutPosition = Context.ProjectViewModelMatrix * vec4(Context.InPosition, 1.0f);
55 | Context.OutPosition = Context.ProjectMatrix * Context.ViewMatrix * Context.ModelMatrix * vec4(Context.InPosition, 1.0f);
56 | wordPosition = Context.OutPosition;
57 | uv0 = Context.InUv0;
58 | }
59 | }
60 | Fs_Shader{
61 | void main(){
62 | // 使用自定义颜色输出
63 | #ifdef Params.color
64 | Context.OutColor = Params.color;
65 | #else
66 | // 使用纹理
67 | #ifdef Params.colorMap
68 | Context.OutColor = texture(Params.colorMap, uv0);
69 | #ifdef Params.alphaDiscard
70 | if(Context.OutColor.a < Params.alphaDiscard){
71 | discard;
72 | }
73 | #endif
74 | #else
75 | Context.OutColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
76 | #endif
77 | #endif
78 | }
79 | }
80 | }
81 | Technology{
82 | Sub_Pass{
83 | Pass ColorPass{
84 | }
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/assets/shadernodes/controls.css:
--------------------------------------------------------------------------------
1 | .control_component_input{
2 | border: 0px;
3 | color: white;
4 | max-width: 150px;
5 | border-radius: 2px;
6 | outline-style: none;
7 | background: #959595;
8 | margin-left: 4px;
9 | margin-right: 4px;
10 | }
11 | .control_component_input:hover{
12 | background: #383838;
13 | }
14 | .textcontrol_component_input{
15 | border: 0px;
16 | color: white;
17 | max-width: 150px;
18 | border-radius: 2px;
19 | outline-style: none;
20 | background: #959595;
21 | margin-left: 4px;
22 | margin-right: 4px;
23 | }
24 | .textcontrol_component_input:hover{
25 | background: #383838;
26 | }
27 |
--------------------------------------------------------------------------------
/src/assets/shadernodes/index.sass:
--------------------------------------------------------------------------------
1 | .connection
2 | overflow: visible !important
3 | width: 1px
4 | height: 10px
5 | .main-path
6 | fill: none
7 | stroke-width: 5px
8 | stroke: steelblue
9 |
--------------------------------------------------------------------------------
/src/assets/shadernodes/shadernodes.css:
--------------------------------------------------------------------------------
1 | /*连接端口,这里设置height:10px防止样式冲突带来的插槽线条偏移*/
2 | .connection{
3 | overflow: visible !important;
4 | width: 1px;
5 | height: 12px;
6 | }
7 | /*连接线条样式*/
8 | .connection .main-path{
9 | fill: none;
10 | stroke-width: 2px;
11 | stroke: rgba(255, 255, 255, 100);
12 | }
13 | /*shader node默认样式*/
14 | .node {
15 | background: #3e3e3e !important;
16 | border: 0px solid #333 !important;
17 | border-radius: 5px !important;
18 | box-shadow: 0 0 15px #000;
19 | }
20 | /*进入shader node样式*/
21 | .node:hover {
22 | background: rgba(120, 120, 120, 0.8) !important;
23 | }
24 | /*选中shader node样式*/
25 | .node.selected {
26 | background: rgb(120, 120, 120) !important;
27 | border: 2px solid white !important;
28 | }
29 |
30 | /*title部分*/
31 | .node .title {
32 | color: #ffffff !important;
33 | }
34 | .node .input-title,
35 | .node .output-title {
36 | margin: 0px 15px !important;
37 | }
38 |
39 | /*socket大小和默认颜色*/
40 | .socket {
41 | width: 15px !important;
42 | height: 15px !important;
43 | margin-left: -7px !important;
44 | background: #96b38a !important;
45 | }
46 | .socket.output {
47 | margin-right: -7px !important;
48 | }
49 |
50 |
51 | /*内置节点title颜色*/
52 | .number .title{
53 | border-radius: 5px 5px 0px 0px !important;
54 | background-color: #2c98b0;
55 | }
56 |
57 | .constructvec2 .title,
58 | .constructvec3 .title,
59 | .constructvec4 .title,
60 | .add .title,
61 | .divide .title,
62 | .multiply .title,
63 | .subtract .title{
64 | border-radius: 5px 5px 0px 0px !important;
65 | background-color: #ee0343;
66 | }
67 |
68 | .floatparam .title,
69 | .boolparam .title,
70 | .vec2param .title,
71 | .vec3param .title,
72 | .vec4param .title,
73 | .texture2dparam .title,
74 | .texturecubeparam .title,
75 | .intparam .title{
76 | border-radius: 5px 5px 0px 0px !important;
77 | background-color: #2e6bb4;
78 | }
79 |
80 | .floatinputstructure .title,
81 | .boolinputstructure .title,
82 | .vec2inputstructure .title,
83 | .vec3inputstructure .title,
84 | .vec4inputstructure .title,
85 | .intinputstructure .title{
86 | border-radius: 5px 5px 0px 0px !important;
87 | background-color: #3ba398;
88 | }
89 | .inputattribute .title,
90 | .inputmatrix .title{
91 | border-radius: 5px 5px 0px 0px !important;
92 | background-color: rgba(255, 255, 255, 0.39);
93 | }
94 |
95 | .floatoutputstructure .title,
96 | .booloutputstructure .title,
97 | .vec2outputstructure .title,
98 | .vec3outputstructure .title,
99 | .vec4outputstructure .title,
100 | .intoutputstructure .title{
101 | border-radius: 5px 5px 0px 0px !important;
102 | background-color: #3ba398;
103 | }
104 |
105 | .samplertexture2d .title{
106 | border-radius: 5px 5px 0px 0px !important;
107 | background-color: #8064c9;
108 | }
109 |
110 | .ifelsebranch .title,
111 | .transformvector3 .title{
112 | border-radius: 5px 5px 0px 0px !important;
113 | background-color: #71b453;
114 | }
115 |
116 | .vertexshaderout .title{
117 | border-radius: 5px 5px 0px 0px !important;
118 | background-color: #d3ae02;
119 | }
120 |
121 | .fragmentshaderout .title{
122 | border-radius: 5px 5px 0px 0px !important;
123 | background-color: #b43329;
124 | }
125 |
126 | /*上下文菜单*/
127 | .context-menu .item {
128 | background-color: #333333dd !important;
129 | border: 0px solid white !important;
130 | padding: 5px 10px !important;
131 | min-width: 150px;
132 | font-family: sans-serif !important;
133 | }
134 | .context-menu .item:hover {
135 | min-width: 150px;
136 | background-color: #2b5088 !important;
137 | }
138 |
--------------------------------------------------------------------------------
/src/assets/textures/lightbulb32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/assets/textures/lightbulb32.png
--------------------------------------------------------------------------------
/src/assets/tools.css:
--------------------------------------------------------------------------------
1 | .topdeftoolbg {
2 | background: rgba(66, 66, 66, 0.53);
3 | width: 100%;
4 | height: 20px;
5 | }
6 | .topdeftoolbg2 {
7 | border-radius: 10px 10px 0 0;
8 | background: rgba(66, 66, 66, 0.53);
9 | width: 100%;
10 | height: 20px;
11 | }
12 | .transparent_div {
13 | background-color: transparent;
14 | width: 100%;
15 | min-height: 100%;
16 | }
17 | /*滚动条样式*/
18 | .transparent_div::-webkit-scrollbar {/*滚动条整体样式*/
19 | width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
20 | height: 4px;
21 | }
22 | .transparent_div::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
23 | border-radius: 5px;
24 | -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
25 | background: rgba(0,0,0,0.2);
26 | }
27 | .transparent_div::-webkit-scrollbar-track {/*滚动条里面轨道*/
28 | -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
29 | border-radius: 0;
30 | background: rgba(0,0,0,0.1);
31 | }
32 | .transparent_div {
33 | border-radius: 10px 10px 0 0;
34 | background: rgba(66, 66, 66, 0.53);
35 | width: 100%;
36 | height: 20px;
37 | }
38 | .btmtoolbg {
39 | border-radius: 10px 10px 0 0;
40 | background: rgba(66, 66, 66, 0.53);
41 | width: 100%;
42 | height: 20px;
43 | }
44 |
45 | .attr_item_top {
46 | font-size: 12px;
47 | text-align: left;
48 | line-height: 20px;
49 | color: #cbcbcb;
50 | border-radius: 5px 5px 0 0;
51 | padding-top: 4px;
52 | padding-bottom: 4px;
53 | margin-top: 2px;
54 | background: rgba(97, 97, 97, 0.53);
55 | /* -50px 是为了属性面板左侧tabs图标大小以及tabContent内部padding*/
56 | width: calc(100% - 50px);
57 | height: 20px;
58 |
59 | /* 文字不被选中*/
60 | -webkit-user-select:none;
61 | -moz-user-select:none;
62 | -ms-user-select:none;
63 | user-select:none;
64 | }
65 |
66 | .attr_item_content {
67 | width: calc(100% - 50px);
68 | border-radius: 0 0 5px 5px;
69 | padding-bottom: 15px;
70 | background: rgba(97, 97, 97, 0.53);
71 | }
72 |
73 | .attr_item {
74 | font-size: 12px;
75 | text-align: left;
76 | line-height: 20px;
77 | color: #cbcbcb;
78 | border-radius: 5px;
79 | padding-top: 4px;
80 | padding-bottom: 4px;
81 | margin-top: 2px;
82 | background: rgba(97, 97, 97, 0.53);
83 | /* -50px 是为了属性面板左侧tabs图标大小以及tabContent内部padding*/
84 | width: calc(100% - 50px);
85 | height: 20px;
86 |
87 | /* 文字不被选中*/
88 | -webkit-user-select:none;
89 | -moz-user-select:none;
90 | -ms-user-select:none;
91 | user-select:none;
92 |
93 | /* shadow*/
94 | box-shadow:0 0 2px #222222;
95 | }
96 |
97 | .attr_item_btm {
98 | border-radius: 0 0 10px 10px;
99 | background: white;
100 | /* -30px 是为了属性面板左侧tabs图标大小*/
101 | width: calc(100% - 30px);
102 | height: 20px;
103 | }
104 |
105 | .component_input{
106 | border: 0px;
107 | border-radius: 2px;
108 | outline-style: none;
109 | background: #777777;
110 | color: #cbcbcb;
111 | margin-left: 4px;
112 | margin-right: 4px;
113 | }
114 | .component_input:hover{
115 | background: #383838;
116 | }
117 |
118 | .component_input_small{
119 | border: 0px;
120 | border-radius: 2px;
121 | outline-style: none;
122 | background: #777777;
123 | color: #cbcbcb;
124 | max-width: 70px;
125 | margin-left: 4px;
126 | margin-right: 4px;
127 | }
128 | .component_input_small:hover{
129 | background: #383838;
130 | }
131 |
132 | .component_select{
133 | border: 0px;
134 | border-radius: 2px;
135 | outline-style: none;
136 | background: #383838;
137 | min-width: 100px;
138 | margin-left: 4px;
139 | margin-right: 4px;
140 | color: #cbcbcb;font-size: 12px;
141 | }
142 |
143 | .component_select:hover{
144 | background: #777777;
145 | }
146 |
147 | .input[type='checkbox']:checked + label:before{
148 | background: #4cd764;
149 | }
150 |
151 | .icon_right {
152 | width: 0;
153 | height: 0;
154 | display: block;
155 | float: left;
156 | transform: rotate(-90deg);
157 | border: 5px solid transparent;
158 | border-color: gray transparent transparent transparent;
159 | margin: 5px;
160 | }
161 |
162 | .icon_btm {
163 | width: 0;
164 | height: 0;
165 | display: block;
166 | float: left;
167 | border: 5px solid transparent;
168 | border-color: gray transparent transparent transparent;
169 | margin: 7px 5px 5px 5px;
170 | }
171 |
172 | /*context menu*/
173 | .vue-contextmenu-listWrapper {
174 | margin: 0;
175 | background: #fff;
176 | z-index: 3000;
177 | position: absolute;
178 | list-style-type: none;
179 | padding: 5px 0;
180 | border-radius: 4px;
181 | font-size: 12px;
182 | font-weight: 400;
183 | min-width: 150px;
184 | color: #c2c2c2;
185 | box-shadow: 4px 4px 5px 0 rgba(0, 0, 0, 0.84);
186 | background-color: #0c0c0c;
187 | }
188 |
189 | .vue-contextmenu-listWrapper .context-menu-list {
190 | margin: 0;
191 | cursor: pointer;
192 | }
193 |
194 | .vue-contextmenu-listWrapper .context-menu-list:hover {
195 | background: #777777;
196 | }
197 |
--------------------------------------------------------------------------------
/src/components/Attributes.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
132 |
133 |
166 |
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
Essential Links
5 |
48 |
Ecosystem
49 |
83 |
84 |
85 |
86 |
96 |
97 |
98 |
114 |
--------------------------------------------------------------------------------
/src/components/Port.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
58 |
59 |
103 |
--------------------------------------------------------------------------------
/src/components/ShaderNode.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{title}}
4 |
5 |
6 |
7 |
8 |
9 |
28 |
29 |
65 |
--------------------------------------------------------------------------------
/src/components/attributes/AttrItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
{{item.type}}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
60 |
61 |
72 |
--------------------------------------------------------------------------------
/src/components/attributes/object/OBJ_Geometry.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
192 |
193 |
203 |
--------------------------------------------------------------------------------
/src/components/attributes/object/OBJ_Node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
148 |
149 |
159 |
--------------------------------------------------------------------------------
/src/components/attributes/object/OBJ_None.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 | 未选择对象
6 |
7 |
8 |
9 |
14 |
15 |
18 |
--------------------------------------------------------------------------------
/src/components/common/BoolComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
53 |
54 |
57 |
--------------------------------------------------------------------------------
/src/components/common/BoolGroupComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
23 |
--------------------------------------------------------------------------------
/src/components/common/ColorComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{content.type}}
4 |
5 |
6 |
7 |
8 |
45 |
46 |
49 |
--------------------------------------------------------------------------------
/src/components/common/CombinationComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
43 |
44 |
58 |
--------------------------------------------------------------------------------
/src/components/common/ImgComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
143 |
144 |
147 |
--------------------------------------------------------------------------------
/src/components/common/NumberComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{content.typename}}
4 |
5 |
6 |
7 |
8 |
9 |
68 |
69 |
72 |
--------------------------------------------------------------------------------
/src/components/common/SelectComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{content.typename}}
4 |
9 |
10 |
11 |
12 |
51 |
52 |
55 |
--------------------------------------------------------------------------------
/src/components/common/TransformComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | {{item.type}}
6 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
36 |
--------------------------------------------------------------------------------
/src/components/common/VectorColorComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
100 |
101 |
104 |
--------------------------------------------------------------------------------
/src/components/common/VectorComponent.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{key}}
4 |
5 |
6 |
7 |
58 |
59 |
62 |
--------------------------------------------------------------------------------
/src/components/shadernodes/common/Color.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
30 |
31 |
34 |
--------------------------------------------------------------------------------
/src/components/shadernodes/common/TextInput.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
31 |
32 |
35 |
--------------------------------------------------------------------------------
/src/components/shadernodes/math/Number.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
31 |
32 |
35 |
--------------------------------------------------------------------------------
/src/components/ui/ContextMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
26 |
27 |
107 |
175 |
--------------------------------------------------------------------------------
/src/components/ui/Tree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 |
7 | {{i.btnName}}
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{i.btnName}}
15 |
16 |
17 |
18 |
19 |
20 |
31 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/editor/Arrow.js:
--------------------------------------------------------------------------------
1 | import Try3d from 'try3d/src/Try3d'
2 | import Mesh from 'try3d/src/Core/WebGL/Mesh'
3 |
4 | export default class Arrow extends Try3d.Geometry{
5 | getType(){
6 | return 'Geometry';
7 | }
8 | static positions = [
9 | 0, 0, 0,
10 | 0, 0, 1, // tip
11 | 0.05, 0, 0.9, // tip right
12 | -0.05, 0, 0.9, // tip left
13 | 0, 0.05, 0.9, // tip top
14 | 0, -0.05, 0.9, // tip bottom
15 | ];
16 |
17 | /**
18 | * 创建一个Arrow。
19 | * @param {Component}[owner]
20 | * @param {String}[cfg.id]
21 | * @param {Vector3}[cfg.extent]
22 | */
23 | constructor (owner, cfg) {
24 | super(owner, cfg);
25 | this._m_TempQuat = new Try3d.Quaternion();
26 | this._m_TempVec = new Try3d.Vector3();
27 |
28 | let len = cfg.extent.length();
29 | let up = Try3d.Vector3.S_UNIT_AXIS_Y;
30 | let dot = cfg.extent.dot(up);
31 | // 说明几乎朝向平行
32 | if(dot >= 0.9){
33 | up = Try3d.Vector3.S_UNIT_AXIS_NEGATIVE_Z;
34 | }
35 | else if(dot <= -0.9){
36 | up = Try3d.Vector3.S_UNIT_AXIS_Z;
37 | }
38 | this.lookAt(this._m_TempQuat, cfg.extent, up);
39 | let mesh = new Try3d.Mesh();
40 | const positions = [];
41 | const indices = [0, 1,
42 | 1, 2,
43 | 1, 3,
44 | 1, 4,
45 | 1, 5];
46 | for(let i = 0;i < Arrow.positions.length;i+=3){
47 | this._m_TempVec.setToInXYZ(Arrow.positions[i], Arrow.positions[i + 1], Arrow.positions[i + 2]);
48 | this._m_TempVec.multLength(len);
49 | this._m_TempQuat.multVec3(this._m_TempVec, this._m_TempVec);
50 | positions.push(this._m_TempVec._m_X);
51 | positions.push(this._m_TempVec._m_Y);
52 | positions.push(this._m_TempVec._m_Z);
53 | }
54 | mesh.setData(Try3d.Mesh.S_POSITIONS, positions);
55 | mesh.setData(Try3d.Mesh.S_INDICES, indices);
56 | mesh.setPrimitive(Try3d.Mesh.S_PRIMITIVE_LINES);
57 | this.setMesh(mesh);
58 | this.updateBound();
59 | }
60 | lookAt(q, direction, up){
61 | let vect3 = new Try3d.Vector3();
62 | vect3.setTo(direction).normal();
63 | let vect1 = new Try3d.Vector3();
64 | vect1.setTo(up);
65 | vect1.cross(direction);
66 | vect1.normal();
67 | let vect2 = new Try3d.Vector3();
68 | vect2.setTo(direction);
69 | vect2.cross(vect1);
70 | vect2.normal();
71 | q.fromAxis(vect1, vect2, vect3);
72 | }
73 |
74 | };
75 |
--------------------------------------------------------------------------------
/src/editor/EditorContext.js:
--------------------------------------------------------------------------------
1 | import Events from 'try3d/src/Core/Util/Events'
2 | import ObjControl from './utils/ObjControl'
3 | import MaterialDefFactory from './shadernodes/MaterialDefFactory'
4 |
5 | export class EditorContext {
6 | static S_MAIN_CONTROL = 'S_MAIN_CONTROL';
7 | // 场景根节点
8 | static S_ROOT_NODE = '_root_Node';
9 | // 世界根节点
10 | static S_WORLD_ROOT_NODE = '_world_root_node';
11 | // 默认辅助几何,不会出现在大纲编辑器列表中
12 | static S_HELPER_NODE = '_helper_node';
13 | static S_HELPER_GRID = '_helper_grid';
14 | static S_HELPER_X_AXIS = '_helper_x_axis';
15 | static S_HELPER_Y_AXIS = '_helper_y_axis';
16 | static S_HELPER_Z_AXIS = '_helper_z_axis';
17 | static S_PICKABLE = 'S_PICKABLE';
18 |
19 | // 一些全局配置信息
20 | static S_LIGHT_BULB_SIZE = 0.3;
21 |
22 | // EVENTS
23 | static S_EVENT_SCENE_LOAD_END = "S_EVENT_SCENE_LOAD_END";
24 |
25 | // 唯一实例
26 | static _s_Instance = null;
27 |
28 | /**
29 | * 返回唯一实例。
30 | * @returns {null}
31 | */
32 | static getInstance(){
33 | if(!EditorContext._s_Instance){
34 | EditorContext._s_Instance = new EditorContext();
35 | }
36 | return EditorContext._s_Instance;
37 | }
38 |
39 | /**
40 | * 返回指定scene,默认返回第0个scene。
41 | * @param {Number}[index]
42 | */
43 | static getScene(index){
44 | // 这里暂时只返回第0个。
45 | if(EditorContext._s_Instance.getRenderer()){
46 | return EditorContext._s_Instance.getRenderer()._scene;
47 | }
48 | return null;
49 | }
50 |
51 | constructor () {
52 | // 所有工作区
53 | this.m_Workspaces = {};
54 |
55 | // 渲染器
56 | this.m_Renderer = null;
57 |
58 | this._m_Events = new Events();
59 | }
60 |
61 | /**
62 | * 注册事件。
63 | * @param {String}[type 事件类型]
64 | * @param {Function}[callback 回调函数]
65 | */
66 | registerEvent(type, callback){
67 | this._m_Events.register(type, callback);
68 | }
69 |
70 | /**
71 | * 卸载指定事件的指定监听器。
72 | * @param {String}[type 事件类型]
73 | * @param {Function}[callback 回调函数]
74 | */
75 | unregisterEvent(type, callback){
76 | this._m_Events.unregister(type, callback);
77 | }
78 |
79 | /**
80 | * 分发事件。
81 | * @param {String}[type 事件类型]
82 | * @param {Object}[data 数据]
83 | */
84 | notifyEvent(type, data){
85 | this._m_Events.trigger(type, data);
86 | }
87 |
88 | setRenderer(renderer){
89 | this.m_Renderer = renderer;
90 | }
91 |
92 | /**
93 | * 初始化编辑器。
94 | */
95 | initEditor(){
96 | let objControl = new ObjControl(EditorContext.getScene(0), {id:'OBJ_CONTROL'});
97 | MaterialDefFactory.initMaterialDefs();
98 | }
99 |
100 | getRenderer(){return this.m_Renderer;}
101 | }
102 |
--------------------------------------------------------------------------------
/src/editor/GlobalConfig.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 全局配置。
3 | * @author JohnKkk
4 | * @date 2022年6月4日15点43分
5 | */
6 | export default class GlobalConfig{
7 | // 默认阴影贴图分辨率
8 | static S_DEFAULT_SHADOW_MAP_SIZE = 1024;
9 | }
10 |
--------------------------------------------------------------------------------
/src/editor/attributes/object/ObjNode.js:
--------------------------------------------------------------------------------
1 | export default class ObjNode {
2 | constructor (obj) {
3 | this._m_Obj = obj;
4 | }
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/src/editor/command/BaseCommand.js:
--------------------------------------------------------------------------------
1 | /**
2 | * BaseCommand。
3 | * @author JohnKkk
4 | * @date 2022年5月11日19点11分
5 | */
6 | export default class BaseCommand {
7 | /**
8 | * BaseCommand。
9 | * @param {Function}[data.redo]
10 | * @param {Function}[data.undo]
11 | * @param {Object}[data.redoData]
12 | * @param {Object}[data.undoData]
13 | */
14 | constructor (data) {
15 | this._mData = {};
16 | this._mData.redo = data.redo;
17 | this._mData.undo = data.undo;
18 | this._mData.redoData = data.redoData;
19 | this._mData.undoData = data.undoData;
20 | }
21 |
22 | redo(){
23 | if(this._mData.redo){
24 | this._mData.redo(this._mData.redoData);
25 | }
26 | }
27 |
28 | undo(){
29 | if(this._mData.undo){
30 | this._mData.undo(this._mData.undoData);
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/editor/command/CommandFactory.js:
--------------------------------------------------------------------------------
1 | import CommandManager from './CommandManager'
2 | import BaseCommand from './BaseCommand'
3 | import Utils from '../utils/Utils'
4 |
5 | /**
6 | * Factory。
7 | * 用于快速创建命令。
8 | * @author JohnKkk
9 | * @date 2022年7月8日13点06分
10 | */
11 | export default class CommandFactory {
12 | static _s_IsCommand = true;
13 | static setIsCommand(isCommand){
14 | CommandFactory._s_IsCommand = isCommand;
15 | }
16 | static isCommand(){
17 | return CommandFactory._s_IsCommand;
18 | }
19 | static createFastCommand(oldValue, undo, newValue, redo, noExc){
20 | let command = new BaseCommand({
21 | redo: redo,
22 | undo: undo,
23 | redoData: newValue,
24 | undoData: oldValue
25 | });
26 | if(!noExc)
27 | CommandManager.getInstance().executeCommand(command);
28 | return command;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/editor/command/CommandManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * CommandManager。
3 | * @author JohnKkk
4 | * @date 2022年5月11日16点57分
5 | */
6 | export default class CommandManager {
7 | // 最多缓存100条命令
8 | static S_MAX_COMMANDS = 100;
9 | static _s_Instance = null;
10 |
11 | constructor () {
12 | this._m_Undos = [];
13 | this._m_Redos = [];
14 | }
15 |
16 | static getInstance(){
17 | if(!CommandManager._s_Instance){
18 | CommandManager._s_Instance = new CommandManager();
19 | }
20 | return CommandManager._s_Instance;
21 | }
22 |
23 | _addToUndos(command){
24 | if((this._m_Undos.length + 1) > CommandManager.S_MAX_COMMANDS){
25 | this._m_Undos.shift();
26 | }
27 | this._m_Undos.push(command);
28 | }
29 |
30 | _addToRedos(command){
31 | if((this._m_Redos.length + 1) > CommandManager.S_MAX_COMMANDS){
32 | this._m_Redos.shift();
33 | }
34 | this._m_Redos.push(command);
35 | }
36 |
37 | /**
38 | * 执行命令。
39 | * @param {Object}[command]
40 | */
41 | executeCommand(command){
42 | if(command){
43 | command.redo();
44 | this._addToUndos(command);
45 | // 一旦开始执行命令,意味着开始一个新命令集,所以清除旧的Redos列表
46 | if(this._m_Redos.length)
47 | this._m_Redos = [];
48 | }
49 | }
50 |
51 | /**
52 | * 撤销最后一个命令。
53 | */
54 | undoLastCommand(){
55 | if(this._m_Undos.length){
56 | let lastCommand = this._m_Undos.pop();
57 | lastCommand.undo();
58 | this._addToRedos(lastCommand);
59 | }
60 | }
61 |
62 | /**
63 | * 重做最后一个命令。
64 | */
65 | redoLastCommand(){
66 | if(this._m_Redos.length){
67 | let lastCommand = this._m_Redos.pop();
68 | lastCommand.redo();
69 | this._addToUndos(lastCommand);
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/src/editor/common/PostFilterFactory.js:
--------------------------------------------------------------------------------
1 | import Try3d from 'try3d/src/Try3d'
2 |
3 | export default class PostFilterFactory {
4 | static _s_PostFilterList;
5 | static postFilterListRefresh(postFilterList){
6 | PostFilterFactory._s_PostFilterList = postFilterList;
7 | }
8 | static getPostFilterList(){
9 | return PostFilterFactory._s_PostFilterList;
10 | }
11 | /**
12 | * DofFilter.
13 | * @param scene
14 | * @param camera
15 | */
16 | static createDofFilter(scene, camera){
17 | let dofFilter = camera.addFilterFromMaterial(new Try3d.Material(scene, {id:'dofFilter', materialDef:Try3d.MaterialDef.parse(Try3d.Internal.S_DOF_FILTER_DEF_DATA)}));
18 | let mat = dofFilter.getMaterial();
19 | let focusDistance = 50;
20 | let focusRange = 10;
21 | let hScale = 1.0;
22 | let vScale = 1.0;
23 | mat.setParam('focusDistance', new Try3d.FloatVars().valueOf(focusDistance));
24 | mat.setParam('focusRange', new Try3d.FloatVars().valueOf(focusRange));
25 | mat.setParam('hScale', new Try3d.FloatVars().valueOf(hScale));
26 | mat.setParam('vScale', new Try3d.FloatVars().valueOf(vScale));
27 | return dofFilter;
28 | }
29 |
30 | /**
31 | * FogFilter.
32 | * @param scene
33 | * @param camera
34 | * @returns {Filter}
35 | */
36 | static createFogFilter(scene, camera){
37 | let fogFilter = camera.addFilterFromMaterial(new Try3d.Material(scene, {id:'fogFilter', materialDef:Try3d.MaterialDef.parse(Try3d.Internal.S_FOG_FILTER_DEF_DATA)}));
38 | let mat = fogFilter.getMaterial();
39 | fogFilter.getMaterial().selectTechnology('Default');
40 | fogFilter.getMaterial().setParam('vNear', new Try3d.FloatVars().valueOf(camera.getNear()));
41 | fogFilter.getMaterial().setParam('vFar', new Try3d.FloatVars().valueOf(camera.getFar()));
42 | fogFilter.getMaterial().setParam('fogNear', new Try3d.FloatVars().valueOf(150));
43 | fogFilter.getMaterial().setParam('fogFar', new Try3d.FloatVars().valueOf(250));
44 | return fogFilter;
45 | }
46 | static createBloomFilter(scene, camera){
47 | let bloomFilter = camera.addFilterFromMaterial(new Try3d.Material(scene, {id:'bloomFilter', materialDef:Try3d.MaterialDef.parse(Try3d.Internal.S_BLOOM_FILTER_DEF_DATA)}));
48 | let mat = bloomFilter.getMaterial();
49 | mat.setParam('extractThreshold', new Try3d.FloatVars().valueOf(0.2));
50 | mat.setParam('bloomIntensity', new Try3d.FloatVars().valueOf(0.25));
51 | return bloomFilter;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/editor/common/ShapeFactory.js:
--------------------------------------------------------------------------------
1 | import {EditorContext} from '../EditorContext'
2 | import Material from './Material'
3 | import Try3d from 'try3d/src/Try3d'
4 | import Utils from '../utils/Utils'
5 | import Arrow from '../Arrow'
6 |
7 | export default class ShapeFactory {
8 | constructor (props) {
9 | }
10 | static createArrow(options){
11 | let scene = options.scene || EditorContext.getScene(0);
12 | let arrow = new Arrow(scene, {id:options.id || 'arrow_' + Utils.nextId(), extent:options.extent});
13 | let mat = null;
14 | if(options.matStrId){
15 | switch (options.matStrId) {
16 | case 'x':
17 | mat = Material.getRedColorMatIns(scene, false);
18 | break;
19 | case 'y':
20 | mat = Material.getGreenColorMatIns(scene, false);
21 | break;
22 | case 'z':
23 | mat = Material.getBlueColorMatIns(scene, false);
24 | break;
25 | case 'light':
26 | default:
27 | mat = Material.getGizmoDefIns(scene, false);
28 | break;
29 | }
30 | }
31 | arrow.setMaterial(mat);
32 | return arrow;
33 | }
34 | static createRound(options){
35 | let radiusMesh = Try3d.MeshFactor.createRoundMesh(3, options.dashed);
36 | let radius = new Try3d.Geometry(options.scene, {id:'radius_' + Utils.nextId()});
37 | radius.receiveShadow(false);
38 | radius.castShadow(false);
39 | radius.setMesh(radiusMesh);
40 | radius.setMaterial(new Try3d.Material(options.scene, {id:'radiusMat_' + Utils.nextId(), materialDef:Material.S_COLOR_MAT}));
41 | radius.updateBound();
42 | radius.setLocalRotationFromEuler(Try3d.MoreMath.toRadians(90), 0, 0);
43 | return radius;
44 | }
45 |
46 | /**
47 | * 创建Box。
48 | * @param options
49 | * @returns {Box}
50 | */
51 | static createBox(options){
52 | let scene = EditorContext.getScene(0);
53 | let box1Mat = Material.getWhiteBasicLightingMatIns(scene, true);
54 | let box = new Try3d.Box(scene, {id:'box_' + Utils.nextId(), xHalf:0.2, yHalf:0.2, zHalf:0.2});
55 | box.setMaterial(box1Mat);
56 | return box;
57 | }
58 |
59 | /**
60 | * 创建Cylinder。
61 | * @param options
62 | * @returns {Cylinder}
63 | */
64 | static createCylinder(options){
65 | let scene = EditorContext.getScene(0);
66 | // 定义一个Cylinder
67 | let cylinder = new Try3d.Cylinder(scene, {id:'cylinder_' + Utils.nextId(), radiusTop:0.0, radiusBottom:0.3, height:1});
68 | // 创建cylinderMat
69 | let cylinderMat = Material.getWhiteBasicLightingMatIns(scene, true);
70 | cylinder.setMaterial(cylinderMat);
71 | return cylinder;
72 | }
73 |
74 | /**
75 | * 创建Sphere。
76 | * @param options
77 | * @returns {Sphere}
78 | */
79 | static createSphere(options){
80 | // 定义一个Sphere
81 | let scene = EditorContext.getScene(0);
82 | let sphere = new Try3d.Sphere(scene, {id:'sphere_' + Utils.nextId(), radius:0.2});
83 | // 创建sphereMat
84 | let sphereMat = Material.getWhiteBasicLightingMatIns(scene, true);
85 | sphere.setMaterial(sphereMat);
86 | return sphere;
87 | }
88 |
89 | /**
90 | * 创建Teapot。
91 | * @param options
92 | * @returns {Teapot}
93 | */
94 | static createTeapot(options){
95 | let scene = EditorContext.getScene(0);
96 | // 定义一个Teapot
97 | let teapot = new Try3d.Teapot(scene, {id:'teapot_' + Utils.nextId()});
98 | let teapotMat = Material.getWhiteBasicLightingMatIns(scene, true);
99 | teapot.setMaterial(teapotMat);
100 | return teapot;
101 | }
102 |
103 | /**
104 | * 创建Torus。
105 | * @param options
106 | * @returns {Torus}
107 | */
108 | static createTorus(options){
109 | let scene = EditorContext.getScene(0);
110 | // 定义一个Torus
111 | let torus = new Try3d.Torus(scene, {id:'torus', tube:0.05, radius:0.2, segmentsR:64, segmentsT:64});
112 | // 创建torusMat
113 | let torusMat = Material.getWhiteBasicLightingMatIns(scene, true);
114 | torus.setMaterial(torusMat);
115 | return torus;
116 | }
117 |
118 | /**
119 | * 创建Plane。
120 | * @param options
121 | * @returns {GroupPlane}
122 | */
123 | static createPlane(options){
124 | let scene = EditorContext.getScene(0);
125 | // 定义一个GroupPlane
126 | let groupPlane = new Try3d.GroupPlane(scene, {id:'groupPlane_' + Utils.nextId(), xSize:4, zSize:4, xSegments:2, zSegments:2});
127 | // 创建groupPlaneMat
128 | let groupPlaneMat = Material.getWhiteBasicLightingMatIns(scene, true);
129 | groupPlane.setMaterial(groupPlaneMat);
130 | return groupPlane;
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/src/editor/leadingPrinciples/LeadingPrinciples.js:
--------------------------------------------------------------------------------
1 | import {EditorContext} from '../EditorContext'
2 | import Try3d from 'try3d/src/Try3d'
3 | import Utils from '../utils/Utils'
4 | import Material from '../common/Material'
5 | import ShapeFactory from '../common/ShapeFactory'
6 |
7 | /**
8 | * 大纲编辑器。
9 | * @author JohnKkk
10 | * @date 2022年5月5日16点48分
11 | */
12 | export default class LeadingPrinciples {
13 | // EVENTs
14 | static S_LEADINGPRINCIPLES_EVENT_SELECTED = 'S_LEADINGPRINCIPLES_EVENT_SELECTED';
15 |
16 | // type
17 | static SG_NODE = 'sg_node';
18 | static SG_GEOMETRY = 'sg_geometry';
19 | static SG_LIGHT = 'sg_light';
20 | constructor () {
21 | }
22 |
23 | /**
24 | * 获取scene数据。
25 | * @param {Array}[parent]
26 | * @param {Node}[node]
27 | * @private
28 | */
29 | _getSceneData(parent, node){
30 | if(node){
31 | // 创建一个新节点
32 | let newNode = {
33 | "id": node.getId(),
34 | "text": node.getName(),
35 | "value": node,
36 | "icon": this._getTypeIcon(node.getType()), // 后续根据node.getType()区分图标
37 | "opened": true,
38 | "selected": false,
39 | "disabled": false,
40 | "loading": false,
41 | "dragDisabled": !this._canDrag(node.getType()),
42 | "dropDisabled": !this._canDrop(node.getType()),
43 | "children": [
44 | ]
45 | };
46 | if(parent){
47 | parent.push(newNode);
48 | }
49 |
50 | if(!(node instanceof Try3d.Light)){
51 | // 查找所有子节点
52 | node.getChildren().forEach(c=>{
53 | // 跳过这个节点
54 | if(c.getName() != EditorContext.S_HELPER_NODE){
55 | this._getSceneData(newNode.children, c);
56 | }
57 | });
58 | }
59 | }
60 | }
61 |
62 | _canDrag(type){
63 | return true;
64 | }
65 |
66 | _canDrop(type){
67 | if(type == 'Node')return true;
68 | return false;
69 | }
70 |
71 | getType(type){
72 | return this._getTypeIcon(type);
73 | }
74 |
75 | _getTypeIcon(type){
76 | switch (type) {
77 | case 'Node':
78 | return 'sg_node';
79 | case 'Geometry':
80 | case 'Box':
81 | case 'Sphere':
82 | case 'Plane':
83 | case 'SkyBox':
84 | return 'sg_geometry';
85 | case 'Light':
86 | case 'DirectionalLight':
87 | case 'PointLight':
88 | case 'SpotLight':
89 | return 'sg_light';
90 | default:
91 | return '';
92 | }
93 | }
94 |
95 | /**
96 | * 返回当前场景数据,以便在大纲编辑器中展示。
97 | * @returns {[]}
98 | */
99 | getData(){
100 | // 将scene解析为大纲面板渲染列表
101 | let data = [];
102 | let editorContext = EditorContext.getInstance();
103 | if(editorContext.getRenderer() && editorContext.getRenderer()._scene){
104 | // 开始转换
105 | // 这里暂时只读取一个scene,后续可以增加为多个scene
106 | let scene = editorContext.getRenderer()._scene.getSceneNode(0).getChildrenAtName(EditorContext.S_ROOT_NODE);
107 | this._getSceneData(data, scene);
108 | }
109 | return data;
110 | }
111 |
112 | newNode(options){
113 | // 创建一个node
114 | let scene = EditorContext.getScene(0);
115 | if(scene){
116 | let newNode = new Try3d.Node(scene, {id:'node_' + Utils.nextId()});
117 | return newNode;
118 | }
119 | return null;
120 | }
121 |
122 | newBox(options){
123 | return ShapeFactory.createBox(options);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/ShaderNodes.js:
--------------------------------------------------------------------------------
1 | import Maths from './math/Maths'
2 | import Textures from './texture/Textures'
3 | import Outputs from './output/Outputs'
4 | import Params from './param/Params'
5 | import Inputs from './input/Inputs'
6 | import Sockets from './Sockets'
7 | import Commons from './common/Commons'
8 |
9 | export default class ShaderNodes {
10 | static _s_Filters = [
11 | Params,
12 | Inputs,
13 | Outputs,
14 | Maths,
15 | Commons,
16 | Textures,
17 | ];
18 |
19 | static _s_VarTypes = {
20 | 'bool':0,
21 | 'int':1,
22 | 'float':2,
23 | 'vec2':3,
24 | 'vec3':4,
25 | 'vec4':5
26 | };
27 |
28 | static filter(component){
29 | for(let f in ShaderNodes._s_Filters){
30 | if(ShaderNodes._s_Filters[f].filter(component)){
31 | return ShaderNodes._s_Filters[f].getGroup();
32 | }
33 | }
34 | return null;
35 | }
36 |
37 | /**
38 | * 注册所有系统节点。
39 | * @param {Object}[editor]
40 | * @param {Object}[engine]
41 | */
42 | static registerShaderNodes(editor, engine){
43 | Sockets.init();
44 | let node = null;
45 | for(let group in ShaderNodes._s_Filters){
46 | for(let shaderNode in ShaderNodes._s_Filters[group]._s_Filters){
47 | node = ShaderNodes._s_Filters[group]._s_Filters[shaderNode];
48 | node = new node();
49 | editor.register(node);
50 | engine.register(node);
51 | }
52 | }
53 | }
54 |
55 | /**
56 | * 提升类型转换,将转换为varType1和varType2中其中的一个类型。
57 | * @param {String}[varType1]
58 | * @param {String}[varType2]
59 | * @return {String}
60 | */
61 | static upgradeCast(varType1, varType2){
62 | return (ShaderNodes._s_VarTypes[varType1] > ShaderNodes._s_VarTypes[varType2]) ? varType1 : varType2;
63 | }
64 | static cast(varType1, varType2){
65 |
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/Sockets.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 |
3 | /**
4 | * Sockets类提供了当前系统内置shaderNode可以连接的插槽类型。
5 | * @author JohnKkk
6 | * @date 2022年7月9日10点21分
7 | */
8 | export default class Sockets{
9 | static s_NoContinueSocket = new Rete.Socket('s_NoContinueSocket');
10 | static s_OperationSocket = new Rete.Socket('s_OperationSocket');
11 | static s_NumSocket = new Rete.Socket('s_NumSocket');
12 | static s_BoolSocket = new Rete.Socket('s_BoolSocket');
13 | static s_UniversalSocket = new Rete.Socket('s_UniversalSocket');
14 | static s_NumArraySocket = new Rete.Socket('s_NumArraySocket');
15 | static s_Texture2DSocket = new Rete.Socket('s_Texture2DSocket');
16 | static s_TextureCubeSocket = new Rete.Socket('s_TextureCubeSocket');
17 | static s_Vector2Socket = new Rete.Socket('s_Vector2Socket');
18 | static s_Vector3Socket = new Rete.Socket('s_Vector3Socket');
19 | static s_Vector4Socket = new Rete.Socket('s_Vector4Socket');
20 | static s_Matrix4Socket = new Rete.Socket('s_Matrix4Socket');
21 | static s_Matrix3Socket = new Rete.Socket('s_Matrix3Socket');
22 |
23 | // Param
24 | static s_PNumSocket = new Rete.Socket('s_PNumSocket');
25 | static s_PBoolSocket = new Rete.Socket('s_PBoolSocket');
26 | static s_PTexture2DSocket = new Rete.Socket('s_PTexture2DSocket');
27 | static s_PTextureCubeSocket = new Rete.Socket('s_PTextureCubeSocket');
28 | static s_PVector2Socket = new Rete.Socket('s_PVector2Socket');
29 | static s_PVector3Socket = new Rete.Socket('s_PVector3Socket');
30 | static s_PVector4Socket = new Rete.Socket('s_PVector4Socket');
31 | static s_PMatrix4Socket = new Rete.Socket('s_PMatrix4Socket');
32 | static s_PMatrix3Socket = new Rete.Socket('s_PMatrix3Socket');
33 |
34 |
35 | static s_Attribute = new Rete.Socket('s_Attribute');
36 | static init(){
37 | // 运行socket的连接
38 | Sockets.s_NumSocket.combineWith(Sockets.s_OperationSocket);
39 | Sockets.s_NumArraySocket.combineWith(Sockets.s_OperationSocket);
40 | Sockets.s_BoolSocket.combineWith(Sockets.s_OperationSocket);
41 | Sockets.s_Vector2Socket.combineWith(Sockets.s_OperationSocket);
42 | Sockets.s_Vector3Socket.combineWith(Sockets.s_OperationSocket);
43 | Sockets.s_Vector4Socket.combineWith(Sockets.s_OperationSocket);
44 | Sockets.s_Texture2DSocket.combineWith(Sockets.s_OperationSocket);
45 | Sockets.s_TextureCubeSocket.combineWith(Sockets.s_OperationSocket);
46 |
47 | Sockets.s_OperationSocket.combineWith(Sockets.s_NumSocket);
48 | Sockets.s_OperationSocket.combineWith(Sockets.s_NumArraySocket);
49 | Sockets.s_OperationSocket.combineWith(Sockets.s_BoolSocket);
50 | Sockets.s_OperationSocket.combineWith(Sockets.s_Vector2Socket);
51 | Sockets.s_OperationSocket.combineWith(Sockets.s_Vector3Socket);
52 | Sockets.s_OperationSocket.combineWith(Sockets.s_Vector4Socket);
53 | Sockets.s_OperationSocket.combineWith(Sockets.s_Texture2DSocket);
54 | Sockets.s_OperationSocket.combineWith(Sockets.s_TextureCubeSocket);
55 |
56 | Sockets.s_PNumSocket.combineWith(Sockets.s_OperationSocket);
57 | Sockets.s_PBoolSocket.combineWith(Sockets.s_OperationSocket);
58 | Sockets.s_PVector2Socket.combineWith(Sockets.s_OperationSocket);
59 | Sockets.s_PVector3Socket.combineWith(Sockets.s_OperationSocket);
60 | Sockets.s_PVector4Socket.combineWith(Sockets.s_OperationSocket);
61 | Sockets.s_PMatrix3Socket.combineWith(Sockets.s_OperationSocket);
62 | Sockets.s_PMatrix4Socket.combineWith(Sockets.s_OperationSocket);
63 |
64 | Sockets.s_OperationSocket.combineWith(Sockets.s_PNumSocket);
65 | Sockets.s_OperationSocket.combineWith(Sockets.s_PBoolSocket);
66 | Sockets.s_OperationSocket.combineWith(Sockets.s_PVector2Socket);
67 | Sockets.s_OperationSocket.combineWith(Sockets.s_PVector3Socket);
68 | Sockets.s_OperationSocket.combineWith(Sockets.s_PVector4Socket);
69 | Sockets.s_OperationSocket.combineWith(Sockets.s_PMatrix3Socket);
70 | Sockets.s_OperationSocket.combineWith(Sockets.s_PMatrix4Socket);
71 |
72 | Sockets.s_PBoolSocket.combineWith(Sockets.s_BoolSocket);
73 | Sockets.s_PNumSocket.combineWith(Sockets.s_NumSocket);
74 | Sockets.s_PVector2Socket.combineWith(Sockets.s_Vector2Socket);
75 | Sockets.s_PVector3Socket.combineWith(Sockets.s_Vector3Socket);
76 | Sockets.s_PVector4Socket.combineWith(Sockets.s_Vector4Socket);
77 | Sockets.s_PMatrix3Socket.combineWith(Sockets.s_Matrix3Socket);
78 | Sockets.s_PMatrix4Socket.combineWith(Sockets.s_Matrix4Socket);
79 | Sockets.s_PTexture2DSocket.combineWith(Sockets.s_Texture2DSocket);
80 | Sockets.s_PTextureCubeSocket.combineWith(Sockets.s_TextureCubeSocket);
81 | Sockets.s_PNumSocket.combineWith(Sockets.s_BoolSocket);
82 | Sockets.s_PVector2Socket.combineWith(Sockets.s_BoolSocket);
83 | Sockets.s_PVector3Socket.combineWith(Sockets.s_BoolSocket);
84 | Sockets.s_PVector4Socket.combineWith(Sockets.s_BoolSocket);
85 | Sockets.s_PMatrix3Socket.combineWith(Sockets.s_BoolSocket);
86 | Sockets.s_PMatrix4Socket.combineWith(Sockets.s_BoolSocket);
87 | Sockets.s_PTexture2DSocket.combineWith(Sockets.s_BoolSocket);
88 | Sockets.s_PTextureCubeSocket.combineWith(Sockets.s_BoolSocket);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/common/Commons.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Commons表示可用的一组常用的节点,包括顶点变换,法线转换,视察计算等。
3 | * @author JohnKkk
4 | * @date 2022年7月20日21点16分
5 | */
6 | import IfElseBranchComponent from './IfElseBranchComponent'
7 | import TransformVector3Component from './TransformVector3Component'
8 |
9 | export default class Commons {
10 | static _s_Filters = [
11 | IfElseBranchComponent,
12 | TransformVector3Component,
13 | ];
14 | static getGroup(){
15 | return 'common';
16 | }
17 | static filter(component){
18 | let r = false;
19 | let targetComponentName = component.name + 'Component';
20 | for(let c in Commons._s_Filters){
21 | if(Commons._s_Filters[c].name == targetComponentName){
22 | r = true;
23 | break;
24 | }
25 | }
26 | return r;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/common/TransformVector3Component.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 | import Sockets from "../Sockets";
3 | import ShaderNode from '../ShaderNode'
4 | export default class TransformVector3Component extends ShaderNode {
5 | constructor() {
6 | super('TransformVector3');
7 | }
8 |
9 | _builder(node) {
10 | let vec4Out = new Rete.Output('vec4Out', 'Vec4Out', Sockets.s_Vector4Socket);
11 |
12 | let inMatrix4x4 = new Rete.Input('inMatrix4x4', 'InMatrix4x4', Sockets.s_Matrix4Socket);
13 | let inVec3 = new Rete.Input('inVec3', 'InVec3', Sockets.s_Vector3Socket);
14 |
15 | node.addOutput(vec4Out);
16 | node.addInput(inVec3);
17 | node.addInput(inMatrix4x4);
18 |
19 | // inputMap
20 | node.data._m_Props._m_InputsMap['inVec3'] = {type:'vec3', varname:this.getVarName(node, 'inVec3')};
21 | node.data._m_Props._m_InputsMap['inMatrix4x4'] = {type:'mat4', varname:this.getVarName(node, 'inMatrix4x4')};
22 | // outputMap
23 | node.data._m_Props._m_OutputsMap['vec4Out'] = {type:'vec4', varname:this.getVarName(node, 'vec4Out'), defaultValue:null};
24 | return node;
25 | }
26 | _getNodeCodeString (node) {
27 | return ' vec4Out = inMatrix4x4 * vec4( inVec3 , 1.0f) ;\n';
28 | }
29 |
30 | _worker(node, inputs, outputs) {
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/BoolInputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class BoolInputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('BoolInputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_BoolSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'bool';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/FloatInputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class FloatInputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('FloatInputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_NumSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'float';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/InputAttributeComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import TextControl from '../param/TextControl'
5 | import Try3d from 'try3d/src/Try3d'
6 |
7 | /**
8 | * InputAttributeComponent,所有可用的顶点输入属性。
9 | * @author JohnKkk
10 | * @date 2022年7月19日19点46分
11 | */
12 | export default class InputAttributeComponent extends ShaderNode{
13 | constructor () {
14 | super('InputAttribute');
15 | }
16 | _getNodeCodeString (node) {
17 | return '';
18 | }
19 |
20 | _getNodeCode(node){
21 | return '';
22 | }
23 |
24 | /**
25 | * 返回输出Socket。
26 | * @return {null}
27 | * @private
28 | */
29 | _outputSocket(){
30 | return null;
31 | }
32 |
33 | /**
34 | * 返回参数类型。
35 | * @return {string}
36 | * @private
37 | */
38 | _paramType(){
39 | return '';
40 | }
41 |
42 | _builder(node) {
43 | let inPosition = new Rete.Output('inPosition', 'InPosition(vec3)', Sockets.s_Vector3Socket);
44 | let inNormal = new Rete.Output('inNormal', 'InNormal(vec3)', Sockets.s_Vector3Socket);
45 | let inTangent = new Rete.Output('inTangent', 'InTangent(vec3)', Sockets.s_Vector3Socket);
46 | let inUv0 = new Rete.Output('inUv0', 'InUv0(vec2)', Sockets.s_Vector2Socket);
47 | let inJoint0 = new Rete.Output('inJoint0', 'InJoint0(int)', Sockets.s_Vector4Socket);
48 | let inWeight0 = new Rete.Output('inWeight0', 'InWeight0(vec4)', Sockets.s_Vector4Socket);
49 |
50 | node.addOutput(inPosition);
51 | node.addOutput(inNormal);
52 | node.addOutput(inTangent);
53 | node.addOutput(inUv0);
54 | node.addOutput(inJoint0);
55 | node.addOutput(inWeight0);
56 |
57 | // outputMap
58 | node.data._m_Props._m_OutputsMap['inPosition'] = {type:Try3d.ShaderSource.Context_Data['Context.InPosition'].type, varname:'Context.InPosition', defaultValue:null};
59 | node.data._m_Props._m_OutputsMap['inNormal'] = {type:Try3d.ShaderSource.Context_Data['Context.InNormal'].type, varname:'Context.InNormal', defaultValue:null};
60 | node.data._m_Props._m_OutputsMap['inTangent'] = {type:Try3d.ShaderSource.Context_Data['Context.InTangent'].type, varname:'Context.InTangent', defaultValue:null};
61 | node.data._m_Props._m_OutputsMap['inUv0'] = {type:Try3d.ShaderSource.Context_Data['Context.InUv0'].type, varname:'Context.InUv0', defaultValue:null};
62 | node.data._m_Props._m_OutputsMap['inJoint0'] = {type:Try3d.ShaderSource.Context_Data['Context.InJoint0'].type, varname:'Context.InJoint0', defaultValue:null};
63 | node.data._m_Props._m_OutputsMap['inWeight0'] = {type:Try3d.ShaderSource.Context_Data['Context.InWeight0'].type, varname:'Context.InWeight0', defaultValue:null};
64 | return node;
65 | }
66 |
67 | _updateBinding(node){
68 | }
69 |
70 | _updateShaderNodeCode(node){
71 | let props = node.data._m_Props;
72 | props._m_ShaderNodeCode = props._m_ShaderNodeCodeSource = '';
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/InputMatrixComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import TextControl from '../param/TextControl'
5 | import Try3d from 'try3d/src/Try3d'
6 |
7 | /**
8 | * InputMatrixComponent,所有可用的上下文输入矩阵。
9 | * @author JohnKkk
10 | * @date 2022年7月29日11点27分
11 | */
12 | export default class InputMatrixComponent extends ShaderNode{
13 | constructor () {
14 | super('InputMatrix');
15 | }
16 | _getNodeCodeString (node) {
17 | return '';
18 | }
19 |
20 | _getNodeCode(node){
21 | return '';
22 | }
23 |
24 | /**
25 | * 返回输出Socket。
26 | * @return {null}
27 | * @private
28 | */
29 | _outputSocket(){
30 | return null;
31 | }
32 |
33 | /**
34 | * 返回参数类型。
35 | * @return {string}
36 | * @private
37 | */
38 | _paramType(){
39 | return '';
40 | }
41 |
42 | _builder(node) {
43 | let inModelMatrix4x4 = new Rete.Output('inModelMatrix4x4', 'InModelMatrix4x4', Sockets.s_Matrix4Socket);
44 | let inViewMatrix4x4 = new Rete.Output('inViewMatrix4x4', 'InViewMatrix4x4', Sockets.s_Matrix4Socket);
45 | let inProjectMatrix4x4 = new Rete.Output('inProjectMatrix4x4', 'InProjectMatrix4x4', Sockets.s_Matrix4Socket);
46 | let inMVPMatrix4x4 = new Rete.Output('inMVPMatrix4x4', 'InMVPMatrix4x4', Sockets.s_Matrix4Socket);
47 | let inVPMatrix4x4 = new Rete.Output('inVPMatrix4x4', 'InProjViewMatrix4x4', Sockets.s_Matrix4Socket);
48 |
49 | node.addOutput(inModelMatrix4x4);
50 | node.addOutput(inViewMatrix4x4);
51 | node.addOutput(inProjectMatrix4x4);
52 | node.addOutput(inMVPMatrix4x4);
53 | node.addOutput(inVPMatrix4x4);
54 |
55 | // outputMap
56 | node.data._m_Props._m_OutputsMap['inModelMatrix4x4'] = {type:Try3d.ShaderSource.Context_Data['Context.ModelMatrix'].type, varname:'Context.ModelMatrix', defaultValue:null};
57 | node.data._m_Props._m_OutputsMap['inViewMatrix4x4'] = {type:Try3d.ShaderSource.Context_Data['Context.ViewMatrix'].type, varname:'Context.ViewMatrix', defaultValue:null};
58 | node.data._m_Props._m_OutputsMap['inProjectMatrix4x4'] = {type:Try3d.ShaderSource.Context_Data['Context.ProjectMatrix'].type, varname:'Context.ProjectMatrix', defaultValue:null};
59 | node.data._m_Props._m_OutputsMap['inMVPMatrix4x4'] = {type:Try3d.ShaderSource.Context_Data['Context.ProjectViewModelMatrix'].type, varname:'Context.ProjectViewModelMatrix', defaultValue:null};
60 | node.data._m_Props._m_OutputsMap['inVPMatrix4x4'] = {type:Try3d.ShaderSource.Context_Data['Context.ProjectViewMatrix'].type, varname:'Context.ProjectViewMatrix', defaultValue:null};
61 | return node;
62 | }
63 |
64 | _updateBinding(node){
65 | }
66 |
67 | _updateShaderNodeCode(node){
68 | let props = node.data._m_Props;
69 | props._m_ShaderNodeCode = props._m_ShaderNodeCodeSource = '';
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/InputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import TextControl from '../param/TextControl'
5 |
6 | /**
7 | * InputStructureComponent,是所有输入结构类型节点的父类。
8 | * @author JohnKkk
9 | * @date 2022年7月19日18点31分
10 | */
11 | export default class InputStructureComponent extends ShaderNode{
12 | _getNodeCodeString (node) {
13 | return '';
14 | }
15 | static getParam(node){
16 | let props = node.data._m_Props;
17 | return {type:props._m_OutputsMap['valueOut'].type, name:props._m_OutputsMap['valueOut'].varname};
18 | }
19 |
20 | _getNodeCode(node){
21 | return '';
22 | }
23 |
24 | /**
25 | * 返回输出Socket。
26 | * @return {null}
27 | * @private
28 | */
29 | _outputSocket(){
30 | return null;
31 | }
32 |
33 | /**
34 | * 返回参数类型。
35 | * @return {string}
36 | * @private
37 | */
38 | _paramType(){
39 | return '';
40 | }
41 |
42 | _builder(node) {
43 | let out = new Rete.Output('valueOut', 'Value', this._outputSocket());
44 | let inVarName = new Rete.Input('inVarName', 'VarName', Sockets.s_NoContinueSocket);
45 |
46 | inVarName.addControl(new TextControl(this.editor, "inVarName"));
47 | node.addInput(inVarName);
48 | node.addOutput(out);
49 |
50 | // outputMap
51 | node.data._m_Props._m_OutputsMap['valueOut'] = {type:this._paramType(), varname:this.getVarName(node, 'valueOut'), defaultValue:null};
52 | return node;
53 | }
54 |
55 | _updateBinding(node){
56 | let nodeProps = node.data._m_Props;
57 | let varname = node.data.inVarName;
58 | if(varname == undefined || varname.trim() == ''){
59 | varname = this.getVarName(node, 'valueOut');
60 | }
61 | nodeProps._m_OutputsMap['valueOut'].varname = varname;
62 | }
63 |
64 | _updateShaderNodeCode(node){
65 | let props = node.data._m_Props;
66 | props._m_ShaderNodeCode = props._m_ShaderNodeCodeSource = '';
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/Inputs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Inputs表示可用的一组输入相关的节点,主要是上下文输入变量,顶点属性。
3 | * 输入节点用于构建最终ShaderCode的上下文变量和顶点属性。
4 | * @author JohnKkk
5 | * @date 2022年7月19日17点33分
6 | */
7 | import BoolInputStructureComponent from './BoolInputStructureComponent'
8 | import IntInputStructureComponent from './IntInputStructureComponent'
9 | import FloatInputStructureComponent from './FloatInputStructureComponent'
10 | import Vec2InputStructureComponent from './Vec2InputStructureComponent'
11 | import Vec3InputStructureComponent from './Vec3InputStructureComponent'
12 | import Vec4InputStructureComponent from './Vec4InputStructureComponent'
13 | import InputAttributeComponent from './InputAttributeComponent'
14 | import InputMatrixComponent from './InputMatrixComponent'
15 |
16 | export default class Inputs {
17 | static _s_InputStructureFilters = [
18 | BoolInputStructureComponent,
19 | IntInputStructureComponent,
20 | FloatInputStructureComponent,
21 | Vec2InputStructureComponent,
22 | Vec3InputStructureComponent,
23 | Vec4InputStructureComponent
24 | ];
25 | static _s_InputContexts = [
26 | InputAttributeComponent
27 | ];
28 | static _s_Filters = [
29 | InputAttributeComponent,
30 | InputMatrixComponent,
31 | BoolInputStructureComponent,
32 | IntInputStructureComponent,
33 | FloatInputStructureComponent,
34 | Vec2InputStructureComponent,
35 | Vec3InputStructureComponent,
36 | Vec4InputStructureComponent
37 | ];
38 | static getGroup(){
39 | return 'input';
40 | }
41 | static filterInputContext(component){
42 | let r = false;
43 | let targetComponentName = component.name + 'Component';
44 | for(let c in Inputs._s_InputContexts){
45 | if(Inputs._s_InputContexts[c].name == targetComponentName){
46 | r = true;
47 | break;
48 | }
49 | }
50 | return r;
51 | }
52 | static filterInputStructure(component){
53 | let r = false;
54 | let targetComponentName = component.name + 'Component';
55 | for(let c in Inputs._s_InputStructureFilters){
56 | if(Inputs._s_Filters[c].name == targetComponentName){
57 | r = true;
58 | break;
59 | }
60 | }
61 | return r;
62 | }
63 | static filter(component){
64 | let r = false;
65 | let targetComponentName = component.name + 'Component';
66 | for(let c in Inputs._s_Filters){
67 | if(Inputs._s_Filters[c].name == targetComponentName){
68 | r = true;
69 | break;
70 | }
71 | }
72 | return r;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/IntInputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class IntInputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('IntInputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_NumSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'int';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/Vec2InputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class Vec2InputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('Vec2InputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Vector2Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec2';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/Vec3InputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class Vec3InputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('Vec3InputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Vector3Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec3';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/input/Vec4InputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import InputStructureComponent from './InputStructureComponent'
3 |
4 | export default class Vec4InputStructureComponent extends InputStructureComponent{
5 | constructor () {
6 | super('Vec4InputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Vector4Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec4';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/AddComponent.js:
--------------------------------------------------------------------------------
1 | import MathComponent from "./MathComponent";
2 |
3 | export default class AddComponent extends MathComponent {
4 | constructor() {
5 | super("Add");
6 | }
7 | doOperation(v1, v2) {
8 | return v1 + v2;
9 | }
10 |
11 | /**
12 | * 返回节点代码。
13 | * @return {string}
14 | * @private
15 | */
16 | _getNodeCodeString (node) {
17 | return ' numOut = inNum1 + inNum2 ;\n';
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/ConstructVec2Component.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Rete from 'rete'
3 | import Sockets from '../Sockets'
4 | import NumberControl from './NumberControl'
5 |
6 | export default class ConstructVec2Component extends ShaderNode{
7 | constructor () {
8 | super('ConstructVec2');
9 | }
10 |
11 | _builder(node) {
12 | let inp1 = new Rete.Input("inX", "X", Sockets.s_NumSocket);
13 | let inp2 = new Rete.Input("inY", "Y", Sockets.s_NumSocket);
14 | let out = new Rete.Output("ResultOut", "Result", Sockets.s_Vector2Socket);
15 |
16 | inp1.addControl(new NumberControl(this.editor, "inX"));
17 | inp2.addControl(new NumberControl(this.editor, "inY"));
18 |
19 | let nodeProps = node.data._m_Props;
20 | // inputMap
21 | nodeProps._m_InputsMap['inX'] = {type:'float', varname:this.getVarName(node, 'inX'), defaultValue:'0.0f'};
22 | nodeProps._m_InputsMap['inY'] = {type:'float', varname:this.getVarName(node, 'inY'), defaultValue:'0.0f'};
23 |
24 | // outputMap
25 | nodeProps._m_OutputsMap['ResultOut'] = {type:'vec2', varname:this.getVarName(node, 'Result'), defaultValue:'vec2( ' + this.getVarName(node, 'inX') + ' , ' + this.getVarName(node, 'inY') + ' )'};
26 |
27 | return node
28 | .addInput(inp1)
29 | .addInput(inp2)
30 | .addOutput(out);
31 | }
32 |
33 | _worker(node, inputs, outputs) {
34 | let nodeProps = node.data._m_Props;
35 | let x = inputs["inX"].length ? inputs["inX"][0] : node.data.inX;
36 | let y = inputs["inY"].length ? inputs["inY"][0] : node.data.inY;
37 | if(x != undefined)
38 | nodeProps._m_InputsMap['inX'].defaultValue = 'float(' + x + ')';
39 | if(y != undefined)
40 | nodeProps._m_InputsMap['inY'].defaultValue = 'float(' + y + ')';
41 |
42 | outputs["ResultOut"] = 'vec2(' + x + ',' + y + ')';
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/ConstructVec3Component.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Rete from 'rete'
3 | import Sockets from '../Sockets'
4 | import NumberControl from './NumberControl'
5 |
6 | export default class ConstructVec3Component extends ShaderNode{
7 | constructor () {
8 | super('ConstructVec3');
9 | }
10 |
11 | _builder(node) {
12 | let inp1 = new Rete.Input("inX", "X", Sockets.s_NumSocket);
13 | let inp2 = new Rete.Input("inY", "Y", Sockets.s_NumSocket);
14 | let inp3 = new Rete.Input("inZ", "Z", Sockets.s_NumSocket);
15 | let out = new Rete.Output("ResultOut", "Result", Sockets.s_Vector3Socket);
16 |
17 | inp1.addControl(new NumberControl(this.editor, "inX"));
18 | inp2.addControl(new NumberControl(this.editor, "inY"));
19 | inp3.addControl(new NumberControl(this.editor, "inZ"));
20 |
21 | let nodeProps = node.data._m_Props;
22 | // inputMap
23 | nodeProps._m_InputsMap['inX'] = {type:'float', varname:this.getVarName(node, 'inX'), defaultValue:'0.0f'};
24 | nodeProps._m_InputsMap['inY'] = {type:'float', varname:this.getVarName(node, 'inY'), defaultValue:'0.0f'};
25 | nodeProps._m_InputsMap['inZ'] = {type:'float', varname:this.getVarName(node, 'inZ'), defaultValue:'0.0f'};
26 |
27 | // outputMap
28 | nodeProps._m_OutputsMap['ResultOut'] = {type:'vec3', varname:this.getVarName(node, 'Result'), defaultValue:'vec3( ' + this.getVarName(node, 'inX') + ' , ' + this.getVarName(node, 'inY') + ' , ' + this.getVarName(node, 'inZ') + ' )'};
29 |
30 | return node
31 | .addInput(inp1)
32 | .addInput(inp2)
33 | .addInput(inp3)
34 | .addOutput(out);
35 | }
36 |
37 | _worker(node, inputs, outputs) {
38 | let nodeProps = node.data._m_Props;
39 | let x = inputs["inX"].length ? inputs["inX"][0] : node.data.inX;
40 | let y = inputs["inY"].length ? inputs["inY"][0] : node.data.inY;
41 | let z = inputs["inZ"].length ? inputs["inZ"][0] : node.data.inZ;
42 | if(x != undefined)
43 | nodeProps._m_InputsMap['inX'].defaultValue = 'float(' + x + ')';
44 | if(y != undefined)
45 | nodeProps._m_InputsMap['inY'].defaultValue = 'float(' + y + ')';
46 | if(z != undefined)
47 | nodeProps._m_InputsMap['inZ'].defaultValue = 'float(' + z + ')';
48 |
49 | outputs["ResultOut"] = 'vec3( ' + x + ' , ' + y + ' , ' + z + ' )';
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/ConstructVec4Component.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Rete from 'rete'
3 | import Sockets from '../Sockets'
4 | import NumberControl from './NumberControl'
5 |
6 | export default class ConstructVec4Component extends ShaderNode{
7 | constructor () {
8 | super('ConstructVec4');
9 | }
10 |
11 | _builder(node) {
12 | let inp1 = new Rete.Input("inX", "X", Sockets.s_NumSocket);
13 | let inp2 = new Rete.Input("inY", "Y", Sockets.s_NumSocket);
14 | let inp3 = new Rete.Input("inZ", "Z", Sockets.s_NumSocket);
15 | let inp4 = new Rete.Input("inW", "W", Sockets.s_NumSocket);
16 | let out = new Rete.Output("ResultOut", "Result", Sockets.s_Vector4Socket);
17 |
18 | inp1.addControl(new NumberControl(this.editor, "inX"));
19 | inp2.addControl(new NumberControl(this.editor, "inY"));
20 | inp3.addControl(new NumberControl(this.editor, "inZ"));
21 | inp4.addControl(new NumberControl(this.editor, "inW"));
22 |
23 | let nodeProps = node.data._m_Props;
24 | // inputMap
25 | nodeProps._m_InputsMap['inX'] = {type:'float', varname:this.getVarName(node, 'inX'), defaultValue:'0.0f'};
26 | nodeProps._m_InputsMap['inY'] = {type:'float', varname:this.getVarName(node, 'inY'), defaultValue:'0.0f'};
27 | nodeProps._m_InputsMap['inZ'] = {type:'float', varname:this.getVarName(node, 'inZ'), defaultValue:'0.0f'};
28 | nodeProps._m_InputsMap['inW'] = {type:'float', varname:this.getVarName(node, 'inW'), defaultValue:'0.0f'};
29 |
30 | // outputMap
31 | nodeProps._m_OutputsMap['ResultOut'] = {type:'vec4', varname:this.getVarName(node, 'Result'), defaultValue:'vec4( ' + this.getVarName(node, 'inX') + ' , ' + this.getVarName(node, 'inY') + ' , ' + this.getVarName(node, 'inZ') + ' , ' + this.getVarName(node, 'inW') + ' )'};
32 |
33 | return node
34 | .addInput(inp1)
35 | .addInput(inp2)
36 | .addInput(inp3)
37 | .addInput(inp4)
38 | .addOutput(out);
39 | }
40 |
41 | _worker(node, inputs, outputs) {
42 | let nodeProps = node.data._m_Props;
43 | let x = inputs["inX"].length ? inputs["inX"][0] : node.data.inX;
44 | let y = inputs["inY"].length ? inputs["inY"][0] : node.data.inY;
45 | let z = inputs["inZ"].length ? inputs["inZ"][0] : node.data.inZ;
46 | let w = inputs["inW"].length ? inputs["inW"][0] : node.data.inW;
47 | if(x != undefined)
48 | nodeProps._m_InputsMap['inX'].defaultValue = 'float(' + x + ')';
49 | if(y != undefined)
50 | nodeProps._m_InputsMap['inY'].defaultValue = 'float(' + y + ')';
51 | if(z != undefined)
52 | nodeProps._m_InputsMap['inZ'].defaultValue = 'float(' + z + ')';
53 | if(w != undefined)
54 | nodeProps._m_InputsMap['inW'].defaultValue = 'float(' + w + ')';
55 |
56 | outputs["ResultOut"] = 'vec3( ' + x + ' , ' + y + ' , ' + z + ' , ' + w + ' )';
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/DivideComponent.js:
--------------------------------------------------------------------------------
1 | import MathComponent from "./MathComponent";
2 |
3 | export default class DivideComponent extends MathComponent {
4 | constructor() {
5 | super("Divide");
6 | }
7 | doOperation(v1, v2) {
8 | return v2 != 0 ? v1 / v2 : 0;
9 | }
10 | _getNodeCodeString (node) {
11 | return ' numOut = inNum1 / inNum2 ;\n';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/MathComponent.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 | import NumberControl from "./NumberControl";
3 | import Sockets from "../Sockets";
4 | import ShaderNode from '../ShaderNode'
5 |
6 | export default class MathComponent extends ShaderNode {
7 | static _s_VarTypes = {
8 | 'bool':0,
9 | 'int':1,
10 | 'float':2,
11 | 'vec2':3,
12 | 'vec3':4,
13 | 'vec4':5
14 | };
15 |
16 | /**
17 | * 提升类型转换,将转换为varType1和varType2中其中的一个类型。
18 | * @param {String}[varType1]
19 | * @param {String}[varType2]
20 | * @return {String}
21 | */
22 | static upgradeCast(varType1, varType2){
23 | return (MathComponent._s_VarTypes[varType1] > MathComponent._s_VarTypes[varType2]) ? varType1 : varType2;
24 | }
25 |
26 | static cast(varType1, varType2){
27 |
28 | }
29 |
30 | doOperation(v1, v2) {
31 | return 0;
32 | }
33 |
34 | _builder(node) {
35 | let inp1 = new Rete.Input("inNum1", "Value 1", Sockets.s_OperationSocket);
36 | let inp2 = new Rete.Input("inNum2", "Value 2", Sockets.s_OperationSocket);
37 | let out = new Rete.Output("numOut", "Result", Sockets.s_OperationSocket);
38 |
39 | inp1.addControl(new NumberControl(this.editor, "inNum1"));
40 | inp2.addControl(new NumberControl(this.editor, "inNum2"));
41 |
42 | let nodeProps = node.data._m_Props;
43 | // inputMap
44 | nodeProps._m_InputsMap['inNum1'] = {type:'float', varname:this.getVarName(node, 'inNum1'), defaultValue:null};
45 | nodeProps._m_InputsMap['inNum2'] = {type:'float', varname:this.getVarName(node, 'inNum2'), defaultValue:null};
46 |
47 | // outputMap
48 | nodeProps._m_OutputsMap['numOut'] = {type:'float', varname:this.getVarName(node, 'numOut'), defaultValue:null};
49 |
50 | return node
51 | .addInput(inp1)
52 | .addInput(inp2)
53 | .addControl(new NumberControl(this.editor, "preview", true))
54 | .addOutput(out);
55 | }
56 | isNumber(value) {
57 | return typeof value === 'number' && isFinite(value);
58 | }
59 |
60 | isNumberObject(n) {
61 | return (Object.prototype.toString.apply(n) === '[object Number]');
62 | }
63 |
64 | isCustomNumber(n){
65 | return this.isNumber(n) || this.isNumberObject(n);
66 | }
67 |
68 | _worker(node, inputs, outputs) {
69 | // if(node.inputs.num1.connections.length){
70 | // let num1Node = this.editor.nodes.find(n=>n.id == node.inputs.num1.connections[0].node);
71 | // console.log('num1Node:',num1Node);
72 | // }
73 | let n1 = inputs["inNum1"].length ? inputs["inNum1"][0] : node.data.inNum1;
74 | let nodeProps = node.data._m_Props;
75 | if(this.isCustomNumber(n1)){
76 | nodeProps._m_InputsMap['inNum1'].defaultValue = n1;
77 | }
78 | else{
79 | nodeProps._m_InputsMap['inNum1'].defaultValue = null;
80 | }
81 | let n2 = inputs["inNum2"].length ? inputs["inNum2"][0] : node.data.inNum2;
82 | if(this.isCustomNumber(n2)){
83 | nodeProps._m_InputsMap['inNum2'].defaultValue = n2;
84 | }
85 | else{
86 | nodeProps._m_InputsMap['inNum2'].defaultValue = null;
87 | }
88 | let sum = this.doOperation(n1, n2);
89 |
90 | this.editor.nodes
91 | .find(n => n.id == node.id)
92 | .controls.get("preview")
93 | .setValue(sum);
94 | outputs["numOut"] = sum;
95 | }
96 |
97 | _updateBinding(node){
98 | let nodeProps = node.data._m_Props;
99 | // 转换类型
100 | let numContinue = super._getContinueNode(node, 'inNum1', 0);
101 | if(numContinue){
102 | let cont = node.inputs['inNum1'].connections[0].output;
103 | if(cont){
104 | nodeProps._m_InputsMap['inNum1'].type = numContinue.data._m_Props._m_OutputsMap[cont].type;
105 | }
106 | }
107 | else{
108 | nodeProps._m_InputsMap['inNum1'].type = 'float';
109 | }
110 | numContinue = super._getContinueNode(node, 'inNum2', 0);
111 | if(numContinue){
112 | let cont = node.inputs['inNum2'].connections[0].output;
113 | if(cont){
114 | nodeProps._m_InputsMap['inNum2'].type = numContinue.data._m_Props._m_OutputsMap[cont].type;
115 | }
116 | }
117 | else{
118 | nodeProps._m_InputsMap['inNum2'].type = 'float';
119 | }
120 | let type1 = nodeProps._m_InputsMap['inNum1'].type;
121 | let type2 = nodeProps._m_InputsMap['inNum2'].type;
122 | let castType = MathComponent.upgradeCast(type1, type2);
123 | if(type1 == castType){
124 | // todo:类型转换,确保运算正确
125 | }
126 | nodeProps._m_OutputsMap['numOut'].type = castType;
127 | this._updateOutputsBinding(node);
128 | super._updateBinding(node);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/Maths.js:
--------------------------------------------------------------------------------
1 | import MathComponent from './MathComponent'
2 | import AddComponent from './AddComponent'
3 | import DivideComponent from './DivideComponent'
4 | import MultiplyComponent from './MultiplyComponent'
5 | import SubtractComponent from './SubtractComponent'
6 | import NumberComponent from './NumberComponent'
7 | import ConstructVec2Component from './ConstructVec2Component'
8 | import ConstructVec3Component from './ConstructVec3Component'
9 | import ConstructVec4Component from './ConstructVec4Component'
10 |
11 | /**
12 | * 表示Maths可用节点。
13 | * @author JohnKkk
14 | * @date 2022年7月12日12点43分
15 | */
16 | export default class Maths {
17 | static _s_Filters = [
18 | ConstructVec2Component,
19 | ConstructVec3Component,
20 | ConstructVec4Component,
21 | AddComponent,
22 | DivideComponent,
23 | MultiplyComponent,
24 | SubtractComponent,
25 | NumberComponent
26 | ];
27 | static getGroup(){
28 | return 'math';
29 | }
30 | static filter(component){
31 | let r = false;
32 | let targetComponentName = component.name + 'Component';
33 | for(let c in Maths._s_Filters){
34 | if(Maths._s_Filters[c].name == targetComponentName){
35 | r = true;
36 | break;
37 | }
38 | }
39 | return r;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/MultiplyComponent.js:
--------------------------------------------------------------------------------
1 | import MathComponent from "./MathComponent";
2 |
3 | export default class MultiplyComponent extends MathComponent {
4 | constructor() {
5 | super("Multiply");
6 | }
7 | doOperation(v1, v2) {
8 | return v1 * v2;
9 | }
10 | _getNodeCodeString (node) {
11 | return ' numOut = inNum1 * inNum2 ;\n';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/NumberComponent.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 | import Sockets from "../Sockets";
3 | import NumberControl from "./NumberControl";
4 | import ShaderNode from '../ShaderNode'
5 | export default class NumberComponent extends ShaderNode {
6 | constructor() {
7 | super('Number');
8 | }
9 |
10 | _builder(node) {
11 | let out = new Rete.Output('numOut', 'Result', Sockets.s_NumSocket);
12 |
13 | node.addControl(new NumberControl(this.editor, "numOut"));
14 | node.addOutput(out);
15 |
16 | // outputMap
17 | node.data._m_Props._m_OutputsMap['numOut'] = {type:'float', varname:this.getVarName(node, 'numOut'), defaultValue:'0.0f'};
18 | return node;
19 | }
20 | _getNodeCodeString (node) {
21 | let r = node.data.numOut != undefined ? 'float(' + node.data.numOut + ')' : '0.0f';
22 | return ' numOut = ' + r + ' ;\n';
23 | }
24 |
25 | _worker(node, inputs, outputs) {
26 | outputs['numOut'] = node.data.numOut;
27 | node.data._m_Props._m_RebuildCode = true;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/NumberControl.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 | import Number from '../../../components/shadernodes/math/Number'
3 |
4 | export default class NumberControl extends Rete.Control {
5 |
6 | constructor(emitter, key, readonly) {
7 | super(key);
8 | this.component = Number;
9 | this.props = { emitter, key, readonly };
10 | }
11 |
12 | setValue(val) {
13 | this.vueContext.value = val;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/SubtractComponent.js:
--------------------------------------------------------------------------------
1 | import MathComponent from "./MathComponent";
2 |
3 | export default class SubtractComponent extends MathComponent {
4 | constructor() {
5 | super("Subtract");
6 | }
7 | doOperation(v1, v2) {
8 | return v1 - v2;
9 | }
10 | _getNodeCodeString (node) {
11 | return ' numOut = inNum1 - inNum2 ;\n';
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/math/Vec2Splitter.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/src/editor/shadernodes/math/Vec2Splitter.js
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/BoolOutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class BoolOutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('BoolOutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_BoolSocket;
16 | }
17 |
18 | _paramType () {
19 | return 'bool';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/FloatOutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class FloatOutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('FloatOutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_NumSocket;
16 | }
17 |
18 | _paramType () {
19 | return 'float';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/FragmentShaderOutComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import MaterialDefFactory from '../MaterialDefFactory'
5 |
6 | export default class FragmentShaderOutComponent extends ShaderNode{
7 | constructor () {
8 | super('FragmentShaderOut');
9 |
10 | }
11 |
12 | _builder (node) {
13 | let inColor = new Rete.Input('inColor', 'Color', Sockets.s_Vector4Socket);
14 | let nodeProps = node.data._m_Props;
15 | // inputMap
16 | nodeProps._m_InputsMap['inColor'] = {type:'vec4', varname:this.getVarName(node, 'inColor'), defaultValue:'vec4(1.0f)'};
17 | nodeProps._m_IsOutput = true;
18 |
19 | return node
20 | .addInput(inColor);
21 | }
22 |
23 | _output (node) {
24 | super._output(node);
25 | MaterialDefFactory.setFsShader(node.data._m_Props._m_ShaderNodeCode);
26 | console.log('matDef:\n' + MaterialDefFactory.toMaterialDefString());
27 | }
28 |
29 | _getNodeCodeString (node) {
30 | return ' Context.OutColor = inColor ;\n';
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/IntOutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class IntOutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('IntOutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_NumSocket;
16 | }
17 |
18 | _paramType () {
19 | return 'int';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/OutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import TextControl from '../param/TextControl'
5 |
6 | /**
7 | * OutputStructureComponent,是所有输出结构类型节点的父类。
8 | * @author JohnKkk
9 | * @date 2022年7月19日20点08分
10 | */
11 | export default class OutputStructureComponent extends ShaderNode{
12 | _getNodeCodeString (node) {
13 | return '';
14 | }
15 | static getParam(node){
16 | let props = node.data._m_Props;
17 | return {type:props._m_InputsMap['varOut'].type, name:props._m_InputsMap['varOut'].varname};
18 | }
19 |
20 | _getNodeCode(node){
21 | return '';
22 | }
23 |
24 | /**
25 | * 返回输出Socket。
26 | * @return {null}
27 | * @private
28 | */
29 | _outputSocket(){
30 | return null;
31 | }
32 |
33 | /**
34 | * 返回输入Socket。
35 | * @return {null}
36 | * @private
37 | */
38 | _inputSocket(){
39 | return null;
40 | }
41 |
42 | /**
43 | * 返回参数类型。
44 | * @return {string}
45 | * @private
46 | */
47 | _paramType(){
48 | return '';
49 | }
50 |
51 | _builder(node) {
52 | let out = new Rete.Output('varOut', 'VarOut', this._outputSocket());
53 | let inVar = new Rete.Input('inVar', 'InVar', this._inputSocket());
54 | let inVarName = new Rete.Input('inVarName', 'VarName', Sockets.s_NoContinueSocket);
55 |
56 | inVarName.addControl(new TextControl(this.editor, "inVarName"));
57 | node.addInput(inVarName);
58 | node.addInput(inVar);
59 | node.addOutput(out);
60 |
61 | // inputMap
62 | node.data._m_Props._m_InputsMap['inVar'] = {type:'', vartype:this._paramType(), varname:this.getVarName(node, 'inVar'), defaultValue:null};
63 | return node;
64 | }
65 |
66 | _updateBinding(node){
67 | let nodeProps = node.data._m_Props;
68 | let varname = node.data.inVarName;
69 | if(varname == undefined || varname.trim() == ''){
70 | varname = this.getVarName(node, 'inVar');
71 | }
72 | nodeProps._m_InputsMap['inVar'].varname = varname;
73 | super._updateBinding(node);
74 | }
75 |
76 | _updateShaderNodeCode(node){
77 | super._updateShaderNodeCode(node);
78 | // let props = node.data._m_Props;
79 | // props._m_ShaderNodeCode = props._m_ShaderNodeCodeSource = '';
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/Outputs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Outputs表示可用的一组输出相关的节点,包括传递结构。
3 | * 输出节点用于构建最终ShaderCode的作用。
4 | * @author JohnKkk
5 | * @date 2022年7月15日16点39分
6 | */
7 | import FragmentShaderOutComponent from './FragmentShaderOutComponent'
8 | import VertexShaderOutComponent from './VertexShaderOutComponent'
9 | import BoolOutputStructureComponent from './BoolOutputStructureComponent'
10 | import IntOutputStructureComponent from './IntOutputStructureComponent'
11 | import FloatOutputStructureComponent from './FloatOutputStructureComponent'
12 | import Vec2OutputStructureComponent from './Vec2OutputStructureComponent'
13 | import Vec3OutputStructureComponent from './Vec3OutputStructureComponent'
14 | import Vec4OutputStructureComponent from './Vec4OutputStructureComponent'
15 |
16 | export default class Outputs {
17 | static _s_OutputStructureFilters = [
18 | BoolOutputStructureComponent,
19 | IntOutputStructureComponent,
20 | FloatOutputStructureComponent,
21 | Vec2OutputStructureComponent,
22 | Vec3OutputStructureComponent,
23 | Vec4OutputStructureComponent,
24 | ];
25 | static _s_Filters = [
26 | BoolOutputStructureComponent,
27 | IntOutputStructureComponent,
28 | FloatOutputStructureComponent,
29 | Vec2OutputStructureComponent,
30 | Vec3OutputStructureComponent,
31 | Vec4OutputStructureComponent,
32 | VertexShaderOutComponent,
33 | FragmentShaderOutComponent
34 | ];
35 | static getGroup(){
36 | return 'output';
37 | }
38 | static filterOutputStructure(component){
39 | let r = false;
40 | let targetComponentName = component.name + 'Component';
41 | for(let c in Outputs._s_OutputStructureFilters){
42 | if(Outputs._s_OutputStructureFilters[c].name == targetComponentName){
43 | r = true;
44 | break;
45 | }
46 | }
47 | return r;
48 | }
49 | static filter(component){
50 | let r = false;
51 | let targetComponentName = component.name + 'Component';
52 | for(let c in Outputs._s_Filters){
53 | if(Outputs._s_Filters[c].name == targetComponentName){
54 | r = true;
55 | break;
56 | }
57 | }
58 | return r;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/Vec2OutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class Vec2OutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('Vec2OutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_Vector2Socket;
16 | }
17 |
18 | _paramType () {
19 | return 'vec2';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/Vec3OutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class Vec3OutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('Vec3OutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_Vector3Socket;
16 | }
17 |
18 | _paramType () {
19 | return 'vec3';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/Vec4OutputStructureComponent.js:
--------------------------------------------------------------------------------
1 | import Sockets from '../Sockets'
2 | import OutputStructureComponent from './OutputStructureComponent'
3 |
4 | export default class Vec4OutputStructureComponent extends OutputStructureComponent{
5 | constructor () {
6 | super('Vec4OutputStructure');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_Attribute;
12 | }
13 |
14 | _inputSocket () {
15 | return Sockets.s_Vector4Socket;
16 | }
17 |
18 | _paramType () {
19 | return 'vec4';
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/output/VertexShaderOutComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import MaterialDefFactory from '../MaterialDefFactory'
5 |
6 | export default class VertexShaderOutComponent extends ShaderNode{
7 | constructor () {
8 | super('VertexShaderOut');
9 |
10 | }
11 |
12 | _builder (node) {
13 | let inPosition = new Rete.Input('inPosition', 'Position', Sockets.s_Vector4Socket);
14 | let inAttributes = new Rete.Input('inAttributes', 'Attributes', Sockets.s_Attribute, true);
15 | let nodeProps = node.data._m_Props;
16 | // inputMap
17 | nodeProps._m_InputsMap['inPosition'] = {type:'vec4', varname:this.getVarName(node, 'inPosition'), defaultValue:'vec4(1.0f)'};
18 | nodeProps._m_IsOutput = true;
19 |
20 | return node
21 | .addInput(inPosition)
22 | .addInput(inAttributes);
23 | }
24 |
25 | _output (node) {
26 | super._output(node);
27 | MaterialDefFactory.setVsShader(node.data._m_Props._m_ShaderNodeCode);
28 | console.log('matDef:\n' + MaterialDefFactory.toMaterialDefString());
29 | }
30 |
31 | _getNodeCodeString (node) {
32 | return ' Context.OutPosition = inPosition ;\n';
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/BoolParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class BoolParamComponent extends ParamComponent{
5 | constructor () {
6 | super('BoolParam');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PBoolSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'bool';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/FloatParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class FloatParamComponent extends ParamComponent{
5 | constructor () {
6 | super('FloatParam');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PNumSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'float';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/IntParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class IntParamComponent extends ParamComponent{
5 | constructor () {
6 | super('IntParam');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PNumSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'int';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/ParamComponent.js:
--------------------------------------------------------------------------------
1 | import ShaderNode from '../ShaderNode'
2 | import Sockets from '../Sockets'
3 | import Rete from 'rete'
4 | import TextControl from './TextControl'
5 |
6 | /**
7 | * ParamComponent,是所有参数类型节点的父类。
8 | * @author JohnKkk
9 | * @date 2022年7月19日09点57分
10 | */
11 | export default class ParamComponent extends ShaderNode{
12 | _getNodeCodeString (node) {
13 | return '';
14 | }
15 | static getParam(node){
16 | let props = node.data._m_Props;
17 | return {type:props._m_OutputsMap['paramOut'].type, name:props._m_OutputsMap['paramOut'].varname};
18 | }
19 |
20 | _getNodeCode(node){
21 | return '';
22 | }
23 |
24 | /**
25 | * 返回输出Socket。
26 | * @return {null}
27 | * @private
28 | */
29 | _outputSocket(){
30 | return null;
31 | }
32 |
33 | /**
34 | * 返回参数类型。
35 | * @return {string}
36 | * @private
37 | */
38 | _paramType(){
39 | return '';
40 | }
41 |
42 | _builder(node) {
43 | let out = new Rete.Output('paramOut', 'Value', this._outputSocket());
44 | let paramName = new Rete.Input('inParamName', 'ParamName', Sockets.s_NoContinueSocket);
45 |
46 | paramName.addControl(new TextControl(this.editor, "inParamName"));
47 | node.addInput(paramName);
48 | node.addOutput(out);
49 |
50 | // outputMap
51 | node.data._m_Props._m_OutputsMap['paramOut'] = {type:this._paramType(), varname:'Params.' + this.getVarName(node, 'paramOut'), defaultValue:null};
52 | return node;
53 | }
54 |
55 | _updateBinding(node){
56 | let nodeProps = node.data._m_Props;
57 | let varname = node.data.inParamName;
58 | if(varname == undefined || varname.trim() == ''){
59 | varname = this.getVarName(node, 'paramOut');
60 | }
61 | nodeProps._m_OutputsMap['paramOut'].varname = 'Params.' + varname;
62 | }
63 |
64 | _updateShaderNodeCode(node){
65 | let props = node.data._m_Props;
66 | props._m_ShaderNodeCode = props._m_ShaderNodeCodeSource = '';
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/Params.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Params表示可用的输入参数。
3 | * @author JohnKkk
4 | * @date 2022年7月12日14点08分
5 | */
6 | import Rete from 'rete';
7 | import FloatParamComponent from './FloatParamComponent'
8 | import IntParamComponent from './IntParamComponent'
9 | import BoolParamComponent from './BoolParamComponent'
10 | import Vec2ParamComponent from './Vec2ParamComponent'
11 | import Vec3ParamComponent from './Vec3ParamComponent'
12 | import Vec4ParamComponent from './Vec4ParamComponent'
13 | import Texture2DParamComponent from './Texture2DParamComponent'
14 | import TextureCubeParamComponent from './TextureCubeParamComponent'
15 |
16 | export default class Params extends Rete.Component{
17 | static _s_Filters = [
18 | FloatParamComponent,
19 | IntParamComponent,
20 | BoolParamComponent,
21 | Vec2ParamComponent,
22 | Vec3ParamComponent,
23 | Vec4ParamComponent,
24 | Texture2DParamComponent,
25 | TextureCubeParamComponent,
26 | ];
27 | static getGroup(){
28 | return 'param';
29 | }
30 | static filter(component){
31 | let r = false;
32 | let targetComponentName = component.name + 'Component';
33 | for(let c in Params._s_Filters){
34 | if(Params._s_Filters[c].name == targetComponentName){
35 | r = true;
36 | break;
37 | }
38 | }
39 | return r;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/TextControl.js:
--------------------------------------------------------------------------------
1 | import Rete from "rete";
2 | import TextInput from '../../../components/shadernodes/common/TextInput'
3 |
4 | export default class TextControl extends Rete.Control {
5 |
6 | constructor(emitter, key, readonly) {
7 | super(key);
8 | this.component = TextInput;
9 | this.props = { emitter, key, readonly };
10 | }
11 |
12 | setValue(val) {
13 | this.vueContext.value = val;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/Texture2DParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class Texture2DParamComponent extends ParamComponent{
5 | constructor () {
6 | super('Texture2DParam');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PTexture2DSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'sampler2D';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/TextureCubeParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class TextureCubeParamComponent extends ParamComponent{
5 | constructor () {
6 | super('TextureCubeParam');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PTextureCubeSocket;
12 | }
13 |
14 | _paramType () {
15 | return 'samplerCube';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/Vec2ParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class Vec2ParamComponent extends ParamComponent{
5 | constructor () {
6 | super('Vec2Param');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PVector2Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec2';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/Vec3ParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class Vec3ParamComponent extends ParamComponent{
5 | constructor () {
6 | super('Vec3Param');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PVector3Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec3';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/param/Vec4ParamComponent.js:
--------------------------------------------------------------------------------
1 | import ParamComponent from './ParamComponent'
2 | import Sockets from '../Sockets'
3 |
4 | export default class Vec4ParamComponent extends ParamComponent{
5 | constructor () {
6 | super('Vec4Param');
7 |
8 | }
9 |
10 | _outputSocket () {
11 | return Sockets.s_PVector4Socket;
12 | }
13 |
14 | _paramType () {
15 | return 'vec4';
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/texture/ColorControl.js:
--------------------------------------------------------------------------------
1 | import Rete from 'rete'
2 | import Color from '../../../components/shadernodes/common/Color'
3 |
4 | export default class ColorControl extends Rete.Control {
5 |
6 | constructor(emitter, key, readonly) {
7 | super(key);
8 | this.component = Color;
9 | this.props = { emitter, key, readonly };
10 | }
11 |
12 | setValue(val) {
13 | this.vueContext.value = val;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/texture/SamplerTexture2DComponent.js:
--------------------------------------------------------------------------------
1 | import Rete from 'rete';
2 | import Sockets from '../Sockets';
3 | import ShaderNode from '../ShaderNode'
4 |
5 | export default class SamplerTexture2DComponent extends ShaderNode{
6 | constructor () {
7 | super('SamplerTexture2D');
8 | }
9 | _builder (node) {
10 | let inTexture2D = new Rete.Input('inTexture2D', 'Texture', Sockets.s_Texture2DSocket);
11 | let inTexCoords = new Rete.Input('inTexCoords', 'TexCoords', Sockets.s_Vector2Socket);
12 | let rgbaOut = new Rete.Output('rgbaOut', "RGBA", Sockets.s_Vector4Socket);
13 | let rOut = new Rete.Output('rOut', "R", Sockets.s_NumSocket);
14 | let gOut = new Rete.Output('gOut', "G", Sockets.s_NumSocket);
15 | let bOut = new Rete.Output('bOut', "B", Sockets.s_NumSocket);
16 | let aOut = new Rete.Output('aOut', "A", Sockets.s_NumSocket);
17 |
18 | let nodeProps = node.data._m_Props;
19 | // inputMap
20 | nodeProps._m_InputsMap['inTexture2D'] = {type:'sampler2D', varname:this.getVarName(node, 'inTexture2D'), defaultValue:null};
21 | nodeProps._m_InputsMap['inTexCoords'] = {type:'vec2', varname:this.getVarName(node, 'inTexCoords'), defaultValue:null};
22 |
23 | // outputMap
24 | nodeProps._m_OutputsMap['rgbaOut'] = {type:'vec4', varname:this.getVarName(node, 'rgbaOut'), defaultValue:'vec4(1.0f)'};
25 | nodeProps._m_OutputsMap['rOut'] = {type:'float', varname:this.getVarName(node, 'rOut'), defaultValue:this.getVarName(node, 'rgbaOut') + '.r'};
26 | nodeProps._m_OutputsMap['gOut'] = {type:'float', varname:this.getVarName(node, 'gOut'), defaultValue:this.getVarName(node, 'rgbaOut') + '.g'};
27 | nodeProps._m_OutputsMap['bOut'] = {type:'float', varname:this.getVarName(node, 'bOut'), defaultValue:this.getVarName(node, 'rgbaOut') + '.b'};
28 | nodeProps._m_OutputsMap['aOut'] = {type:'float', varname:this.getVarName(node, 'aOut'), defaultValue:this.getVarName(node, 'rgbaOut') + '.a'};
29 |
30 | return node
31 | .addInput(inTexture2D)
32 | .addInput(inTexCoords)
33 | .addOutput(rgbaOut)
34 | .addOutput(rOut)
35 | .addOutput(gOut)
36 | .addOutput(bOut)
37 | .addOutput(aOut);
38 | }
39 | _updateBinding(node){
40 | let nodeProps = node.data._m_Props;
41 | let varname = null;
42 | let inTexture2DContinue = super._getContinueNode(node, 'inTexture2D', 0);
43 | if(inTexture2DContinue) {
44 | let cont = node.inputs['inTexture2D'].connections[0].output;
45 | if(cont){
46 | varname = inTexture2DContinue.data._m_Props._m_OutputsMap[cont].varname;
47 | }
48 | }
49 | if(varname == undefined || varname.trim() == ''){
50 | varname = this.getVarName(node, 'inTexture2D');
51 | nodeProps._m_InputsMap['inTexture2D'].skip = false;
52 | }
53 | else{
54 | nodeProps._m_InputsMap['inTexture2D'].skip = true;
55 | }
56 | nodeProps._m_RebuildCode = true;
57 | nodeProps._m_InputsMap['inTexture2D'].varname = varname;
58 | super._updateBinding(node);
59 | nodeProps._m_InputsBinding['inTexture2D'] = null;
60 | }
61 | _getNodeCodeString (node) {
62 | return ' rgbaOut = texture( inTexture2D , inTexCoords ) ;\n';
63 | }
64 |
65 | _worker (node, inputs, outputs, ...args) {
66 | // 正常输出用于节点展示
67 | outputs['rgba'] = node.data.rgba;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/editor/shadernodes/texture/Textures.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Textures表示可用的一组Texture计算相关的节点。
3 | * @author JohnKkk
4 | * @date 2022年7月12日14点54分
5 | */
6 | import SamplerTexture2DComponent from './SamplerTexture2DComponent'
7 |
8 | export default class Textures {
9 | static _s_Filters = [
10 | SamplerTexture2DComponent
11 | ];
12 | static getGroup(){
13 | return 'texture';
14 | }
15 | static filter(component){
16 | let r = false;
17 | let targetComponentName = component.name + 'Component';
18 | for(let c in Textures._s_Filters){
19 | if(Textures._s_Filters[c].name == targetComponentName){
20 | r = true;
21 | break;
22 | }
23 | }
24 | return r;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/editor/utils/ColorMath.js:
--------------------------------------------------------------------------------
1 | let tmpComponent;
2 |
3 | const ColorMath = {
4 | hsv_to_rgb: function(h, s, v) {
5 | const hi = Math.floor(h / 60) % 6;
6 |
7 | const f = h / 60 - Math.floor(h / 60);
8 | const p = v * (1.0 - s);
9 | const q = v * (1.0 - (f * s));
10 | const t = v * (1.0 - ((1.0 - f) * s));
11 |
12 | const c = [
13 | [v, t, p],
14 | [q, v, p],
15 | [p, v, t],
16 | [p, q, v],
17 | [t, p, v],
18 | [v, p, q]
19 | ][hi];
20 |
21 | return {
22 | r: c[0] * 255,
23 | g: c[1] * 255,
24 | b: c[2] * 255
25 | };
26 | },
27 |
28 | rgb_to_hsv: function(r, g, b) {
29 | const min = Math.min(r, g, b);
30 | const max = Math.max(r, g, b);
31 | const delta = max - min;
32 | let h;
33 | let s;
34 |
35 | if (max !== 0) {
36 | s = delta / max;
37 | } else {
38 | return {
39 | h: NaN,
40 | s: 0,
41 | v: 0
42 | };
43 | }
44 |
45 | if (r === max) {
46 | h = (g - b) / delta;
47 | } else if (g === max) {
48 | h = 2 + (b - r) / delta;
49 | } else {
50 | h = 4 + (r - g) / delta;
51 | }
52 | h /= 6;
53 | if (h < 0) {
54 | h += 1;
55 | }
56 |
57 | return {
58 | h: h * 360,
59 | s: s,
60 | v: max / 255
61 | };
62 | },
63 |
64 | rgb_to_hex: function(r, g, b) {
65 | let hex_r = (r * 255).toFixed(0).toString(16);
66 | let hex_g = (g * 255).toFixed(0).toString(16);
67 | let hex_b = (b * 255).toFixed(0).toString(16);
68 | return '#' + hex_r + hex_g + hex_b;
69 | },
70 |
71 | rgbToHex(r, g, b) {
72 | r = (r * 255).toFixed(0);
73 | g = (g * 255).toFixed(0);
74 | b = (b * 255).toFixed(0);
75 | if(r == 0 && g == 0 && b == 0){
76 | return '#000000';
77 | }
78 | return '#' + ((r << 16) | (g << 8) | b).toString(16);
79 | },
80 |
81 | hex_to_rgb: function(hex){
82 | let b = this.component_from_hex(hex, 0) / 255.0;
83 | let g = this.component_from_hex(hex, 1) / 255.0;
84 | let r = this.component_from_hex(hex, 2) / 255.0;
85 | return {r, g, b};
86 | },
87 |
88 | hexToRgba(hex, opacity) {
89 | return {r:parseInt("0x" + hex.slice(1, 3)) / 255.0, g:parseInt("0x" + hex.slice(3, 5)) / 255.0, b:parseInt("0x" + hex.slice(5, 7)) / 255.0};
90 | },
91 |
92 | component_from_hex: function(hex, componentIndex) {
93 | return (hex >> (componentIndex * 8)) & 0xFF;
94 | },
95 |
96 | hex_with_component: function(hex, componentIndex, value) {
97 | return value << (tmpComponent = componentIndex * 8) | (hex & ~(0xFF << tmpComponent));
98 | }
99 | };
100 |
101 | export default ColorMath;
102 |
--------------------------------------------------------------------------------
/src/editor/utils/Utils.js:
--------------------------------------------------------------------------------
1 | export default class Utils {
2 | static _s_Id = -1;
3 | static _s_ShaderNodeId = 0;
4 | static nextId(){
5 | return Utils._s_Id++;
6 | }
7 | static nextShaderNodeId(){
8 | return Utils._s_ShaderNodeId++;
9 | }
10 |
11 | static getObjectType(type){
12 | switch (type) {
13 | case 'Node':
14 | return 'Node';
15 | case 'Geometry':
16 | case 'Box':
17 | case 'Sphere':
18 | case 'Plane':
19 | case 'SkyBox':
20 | return 'Geometry';
21 | case 'Light':
22 | case 'DirectionalLight':
23 | case 'PointLight':
24 | case 'SpotLight':
25 | return 'Light';
26 | default:
27 | return '';
28 | }
29 | }
30 |
31 | /**
32 | * 复制一个对象。
33 | * @param {Object}[object]
34 | * @param {String}[filterKey 过滤key]
35 | * @param {Object}[filterValue 过滤key对应的value]
36 | * @returns {{}}
37 | */
38 | static copyObj(object, filterKey, filterValue){
39 | let result = {};
40 | for(let k in object){
41 | if(k == filterKey){
42 | result[k] = filterValue;
43 | }
44 | else{
45 | result[k] = object[k];
46 | }
47 | }
48 | return result;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/editor/viewer/Viewer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 3D视图编辑器。
3 | * @author JohnKkk
4 | * @date 2022年6月27日19点01分
5 | */
6 | export default class Viewer {
7 | static S_VIEWER_EVENT_SELECTED = 'S_VIEWER_EVENT_SELECTED';
8 | static S_VIEWER_EVENT_SELECTED2 = 'S_VIEWER_EVENT_SELECTED2';
9 | static S_VIEWER_OBJECT_UPDATE = 'S_VIEWER_OBJECT_UPDATE';
10 | static S_VIEWER_MATERIAL_DEF_COMPILE = 'S_VIEWER_MATERIAL_DEF_COMPILE';
11 | // todo:
12 | // 封装Viewer部分常见操作
13 | }
14 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import ProduceEdit from './router/produce'
5 | import Produce from './Produce'
6 |
7 | Vue.config.productionTip = false
8 |
9 | /* eslint-disable no-new */
10 | new Vue({
11 | el: '#Produce',
12 | router: ProduceEdit,
13 | components: { Produce },
14 | template: ''
15 | })
16 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import HelloWorld from '@/components/HelloWorld'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | name: 'HelloWorld',
12 | component: HelloWorld
13 | }
14 | ]
15 | })
16 |
--------------------------------------------------------------------------------
/src/router/produce.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import ProduceEdit from 'vue-router'
3 | import Port from '@/components/Port'
4 | import vcolorpicker from 'vcolorpicker'
5 | import ContextMenu from '../components/ui/ContextMenu'
6 |
7 | Vue.component('VueContextMenu', ContextMenu)
8 | Vue.use(vcolorpicker)
9 | Vue.use(ProduceEdit)
10 | /**
11 | * Produce编辑器。
12 | * @author JhonKkk
13 | * @date 2021年8月13日17点36分
14 | */
15 | export default new ProduceEdit({
16 | routes: [
17 | {
18 | path: '/',
19 | name: 'Port',
20 | component: Port
21 | }
22 | ]
23 | })
24 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JohnLKkk/Produce/c1faed67e6365bb5e35724fe549f9d869a6c5140/static/.gitkeep
--------------------------------------------------------------------------------
/static/MaterialDefinitionSource.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MaterialDefinitionSource
6 |
7 |
9 |
10 |
11 |
18 |
19 |
20 |
21 | matDef:
22 | Def 8_mat{
23 | SubTechnology defaultSubDraw{
24 | Vs_Shader{
25 | void main(){
26 | // VertexShaderOut_3 : Begin
27 |
28 |
29 | // CommonVert_2 : Begin
30 | vec3 CommonVert_2_inPosition = Context.InPosition;
31 | mat4 CommonVert_2_inMatrix = Context.ProjectViewModelMatrix;
32 | vec4 CommonVert_2_projPositionOut;
33 | CommonVert_2_projPositionOut=CommonVert_2_inMatrix* vec4(CommonVert_2_inPosition, 1.0f) ;
34 | // CommonVert_2 : End
35 |
36 | vec4 VertexShaderOut_3_inPosition = CommonVert_2_projPositionOut;
37 | Context.OutPosition =VertexShaderOut_3_inPosition;
38 | // VertexShaderOut_3 : End
39 |
40 | }
41 | }
42 | Fs_Shader{
43 | void main(){
44 |
45 | }
46 | }
47 | Technology{
48 | Sub_Pass{
49 | Pass defaultSubDraw{
50 | }
51 | }
52 | }
53 |
54 |
55 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/static/heighlight/default.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | Theme: Default
3 | Description: Original highlight.js style
4 | Author: (c) Ivan Sagalaev
5 | Maintainer: @highlightjs/core-team
6 | Website: https://highlightjs.org/
7 | License: see project LICENSE
8 | Touched: 2021
9 | */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}
10 |
--------------------------------------------------------------------------------
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test
6 |
14 |
15 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/test.txt:
--------------------------------------------------------------------------------
1 | Def 8_mat{
2 | SubTechnology defaultSubDraw{
3 | Vs_Shader{
4 | void main(){
5 | // VertexShaderOut_3 : Begin
6 |
7 |
8 | // TransformVector3_2 : Begin
9 | vec3 TransformVector3_2_inVec3 = Context.InPosition;
10 | mat4 TransformVector3_2_inMatrix4x4 = Context.ProjectViewModelMatrix;
11 | vec4 TransformVector3_2_vec4Out;
12 | TransformVector3_2_vec4Out=TransformVector3_2_inMatrix4x4* vec4(TransformVector3_2_inVec3, 1.0f) ;
13 | // TransformVector3_2 : End
14 |
15 | vec4 VertexShaderOut_3_inPosition = TransformVector3_2_vec4Out;
16 | Context.OutPosition =VertexShaderOut_3_inPosition;
17 | // VertexShaderOut_3 : End
18 |
19 | }
20 | }
21 | Fs_Shader{
22 | void main(){
23 | // FragmentShaderOut_4 : Begin
24 | // ConstructVec4_5 : Begin
25 | float ConstructVec4_5_inX = float(1);
26 | float ConstructVec4_5_inY = float(0);
27 | float ConstructVec4_5_inZ = float(0);
28 | float ConstructVec4_5_inW = float(1);
29 | vec4 ConstructVec4_5_Result = vec4( inX , inY , inZ , inW );
30 | // ConstructVec4_5 : End
31 |
32 | vec4 FragmentShaderOut_4_inColor = ConstructVec4_5_Result;
33 | Context.OutColor =FragmentShaderOut_4_inColor;
34 | // FragmentShaderOut_4 : End
35 |
36 | }
37 | }
38 | Technology{
39 | Sub_Pass{
40 | Pass defaultSubDraw{
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function (selector, count) {
11 | this.message = 'Testing if element <' + selector + '> has count: ' + count
12 | this.expected = count
13 | this.pass = function (val) {
14 | return val === this.expected
15 | }
16 | this.value = function (res) {
17 | return res.value
18 | }
19 | this.command = function (cb) {
20 | var self = this
21 | return this.api.execute(function (selector) {
22 | return document.querySelectorAll(selector).length
23 | }, [selector], function (res) {
24 | cb.call(self, res)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 |
4 | const webpack = require('webpack')
5 | const DevServer = require('webpack-dev-server')
6 |
7 | const webpackConfig = require('../../build/webpack.prod.conf')
8 | const devConfigPromise = require('../../build/webpack.dev.conf')
9 |
10 | let server
11 |
12 | devConfigPromise.then(devConfig => {
13 | const devServerOptions = devConfig.devServer
14 | const compiler = webpack(webpackConfig)
15 | server = new DevServer(compiler, devServerOptions)
16 | const port = devServerOptions.port
17 | const host = devServerOptions.host
18 | return server.listen(port, host)
19 | })
20 | .then(() => {
21 | // 2. run the nightwatch test suite against it
22 | // to run in additional browsers:
23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
24 | // 2. add it to the --env flag below
25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
26 | // For more information on Nightwatch's config file, see
27 | // http://nightwatchjs.org/guide#settings-file
28 | let opts = process.argv.slice(2)
29 | if (opts.indexOf('--config') === -1) {
30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
31 | }
32 | if (opts.indexOf('--env') === -1) {
33 | opts = opts.concat(['--env', 'chrome'])
34 | }
35 |
36 | const spawn = require('cross-spawn')
37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
38 |
39 | runner.on('exit', function (code) {
40 | server.close()
41 | process.exit(code)
42 | })
43 |
44 | runner.on('error', function (err) {
45 | server.close()
46 | throw err
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | },
5 | "globals": {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleFileExtensions: [
6 | 'js',
7 | 'json',
8 | 'vue'
9 | ],
10 | moduleNameMapper: {
11 | '^@/(.*)$': '/src/$1'
12 | },
13 | transform: {
14 | '^.+\\.js$': '/node_modules/babel-jest',
15 | '.*\\.(vue)$': '/node_modules/vue-jest'
16 | },
17 | testPathIgnorePatterns: [
18 | '/test/e2e'
19 | ],
20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
21 | setupFiles: ['/test/unit/setup'],
22 | mapCoverage: true,
23 | coverageDirectory: '/test/unit/coverage',
24 | collectCoverageFrom: [
25 | 'src/**/*.{js,vue}',
26 | '!src/main.js',
27 | '!src/router/index.js',
28 | '!**/node_modules/**'
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .toEqual('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------