Browse Source

GLSL Support Round 1: Syntax Highlighting (#156)

* Basic file recognition

* Added block comments

* Fixed preprocessor to work with indents

* Added operators and various brackets

* Added keywords and builtin types

* Added builtin variables based on glsl 4.4 and JME wiki. Logic behind it would need some tweaking.

* Added builtin functions based on glsl 4.4 and reworked logic behind parsing keywords.

* Added icons by ogli,
grizeldi 7 years ago
parent
commit
fc36f82a50
24 changed files with 1414 additions and 9 deletions
  1. 1 1
      branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
  2. 2 2
      branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
  3. 1 1
      branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties
  4. 8 0
      jme3-glsl-highlighter/build.xml
  5. 7 0
      jme3-glsl-highlighter/manifest.mf
  6. 45 0
      jme3-glsl-highlighter/nbproject/build-impl.xml
  7. 8 0
      jme3-glsl-highlighter/nbproject/genfiles.properties
  8. 3 0
      jme3-glsl-highlighter/nbproject/project.properties
  9. 163 0
      jme3-glsl-highlighter/nbproject/project.xml
  10. 1 0
      jme3-glsl-highlighter/nbproject/suite.properties
  11. 3 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/Bundle.properties
  12. 60 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/GlslLanguage.java
  13. 15 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/layer.xml
  14. 486 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslKeywordLibrary.java
  15. 61 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslLanguageHierarchy.java
  16. 258 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslLexer.java
  17. 70 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslTokenID.java
  18. 4 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/FragmentShader.frag
  19. 163 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/GlslDataObject.java
  20. 7 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/VertexShader.vert
  21. BIN
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/fragIcon.png
  22. 41 0
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/package-info.java
  23. BIN
      jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/vertIcon.png
  24. 7 5
      nbproject/project.properties

+ 1 - 1
branding/core/core.jar/org/netbeans/core/startup/Bundle.properties

@@ -1,6 +1,6 @@
 #Updated by build script
 #Sat, 27 Aug 2011 22:46:29 +0200
-currentVersion=jMonkeyEngine SDK 3.1.0-alpha5
+currentVersion=jMonkeyEngine SDK 3.2.0-glsl-SNAPSHOT
 LBL_splash_window_title=Starting jMonkeyEngine SDK
 SPLASH_HEIGHT=350
 SPLASH_WIDTH=500

+ 2 - 2
branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties

@@ -1,4 +1,4 @@
 #Updated by build script
 #Sat, 27 Aug 2011 22:46:29 +0200
-CTL_MainWindow_Title=jMonkeyEngine SDK PBRisComing-SNAPSHOT
-CTL_MainWindow_Title_No_Project=jMonkeyEngine SDK PBRisComing-SNAPSHOT
+CTL_MainWindow_Title=jMonkeyEngine SDK 3.2.0-glsl-SNAPSHOT
+CTL_MainWindow_Title_No_Project=jMonkeyEngine SDK 3.2.0-glsl-SNAPSHOT

+ 1 - 1
branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties

@@ -1,3 +1,3 @@
-LBL_Copyright=<p><em>Copyright &copy; 2016 jMonkeyEngine.\n<br>Please visit <a style="color: #f3c802;" href="http://jmonkeyengine.org">http://jmonkeyengine.org</a> for more information.</em></p><p>Icons sets : <ul><li><a style="color: #f3c802;" href="http://brankic1979.com/icons/">Brankic1979</a></li><li><a style="color: #f3c802;" href="http://www.entypo.com/index.php">Entypo+</a></li><ul> </p>
+LBL_Copyright=<p><em>Copyright &copy; 2018 jMonkeyEngine.\n<br>Please visit <a style="color: #f3c802;" href="http://jmonkeyengine.org">http://jmonkeyengine.org</a> for more information.</em></p><p>Icons sets : <ul><li><a style="color: #f3c802;" href="http://brankic1979.com/icons/">Brankic1979</a></li><li><a style="color: #f3c802;" href="http://www.entypo.com/index.php">Entypo+</a></li><li><a style="color: #f3c802;" href="https://hub.jmonkeyengine.org/u/ogli">Ogli</a> (edited by <a style="color: #f3c802;" href="https://hub.jmonkeyengine.org/u/grizeldi">grizeldi</a></li><ul> </p>
 updates_not_found=<p style="margin: 0"><b>Updates:</b> jMonkeyEngine SDK is updated to version {0}</p>\n 
 URL_ON_IMG=http://jmonkeyengine.org/

+ 8 - 0
jme3-glsl-highlighter/build.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
+<!-- for some information on what you could do (e.g. targets to override). -->
+<!-- If you delete this file and reopen the project it will be recreated. -->
+<project name="com.jme3.gde.glsl.highlighter" default="netbeans" basedir=".">
+    <description>Builds, tests, and runs the project com.jme3.gde.glsl.highlighter.</description>
+    <import file="nbproject/build-impl.xml"/>
+</project>

+ 7 - 0
jme3-glsl-highlighter/manifest.mf

@@ -0,0 +1,7 @@
+Manifest-Version: 1.0
+AutoUpdate-Show-In-Client: true
+OpenIDE-Module: com.jme3.gde.glsl.highlighter
+OpenIDE-Module-Layer: com/jme3/gde/glsl/highlighter/layer.xml
+OpenIDE-Module-Localizing-Bundle: com/jme3/gde/glsl/highlighter/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+

+ 45 - 0
jme3-glsl-highlighter/nbproject/build-impl.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+*** GENERATED FROM project.xml - DO NOT EDIT  ***
+***         EDIT ../build.xml INSTEAD         ***
+-->
+<project name="com.jme3.gde.glsl.highlighter-impl" basedir="..">
+    <fail message="Please build using Ant 1.7.1 or higher.">
+        <condition>
+            <not>
+                <antversion atleast="1.7.1"/>
+            </not>
+        </condition>
+    </fail>
+    <property file="nbproject/private/suite-private.properties"/>
+    <property file="nbproject/suite.properties"/>
+    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
+    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
+    <property file="${suite.dir}/nbproject/platform.properties"/>
+    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="name"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{name}" value="${@{value}}"/>
+        </sequential>
+    </macrodef>
+    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
+        <attribute name="property"/>
+        <attribute name="value"/>
+        <sequential>
+            <property name="@{property}" value="@{value}"/>
+        </sequential>
+    </macrodef>
+    <property file="${user.properties.file}"/>
+    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
+    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
+        <condition>
+            <not>
+                <contains string="${cluster.path.evaluated}" substring="platform"/>
+            </not>
+        </condition>
+    </fail>
+    <import file="${harness.dir}/build.xml"/>
+</project>

+ 8 - 0
jme3-glsl-highlighter/nbproject/genfiles.properties

@@ -0,0 +1,8 @@
+build.xml.data.CRC32=9a73419f
+build.xml.script.CRC32=0322e3d8
[email protected]
+# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
+# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
+nbproject/build-impl.xml.data.CRC32=9a73419f
+nbproject/build-impl.xml.script.CRC32=f767ba38
+nbproject/[email protected]

+ 3 - 0
jme3-glsl-highlighter/nbproject/project.properties

@@ -0,0 +1,3 @@
+javac.source=1.7
+javac.compilerargs=-Xlint -Xlint:-serial
+project.license=jme license

+ 163 - 0
jme3-glsl-highlighter/nbproject/project.xml

@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.apisupport.project</type>
+    <configuration>
+        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+            <code-name-base>com.jme3.gde.glsl.highlighter</code-name-base>
+            <suite-component/>
+            <module-dependencies>
+                <dependency>
+                    <code-name-base>org.netbeans.api.templates</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>1.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.core.multiview</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.44.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.csl.api</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>2.54.1.2.1.1.8.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>1.87.1.6.3.23.55</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>3</release-version>
+                        <specification-version>4.7.1.23.3.55</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.lexer</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>2</release-version>
+                        <specification-version>1.63.1.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.netbeans.modules.settings</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <release-version>1</release-version>
+                        <specification-version>1.49.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.awt</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.67.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.dialogs</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.42.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.filesystems</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.10.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.loaders</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.66.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.modules</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.48.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.nodes</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>7.45.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.text</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.67.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.7.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.lookup</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>8.33.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.util.ui</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>9.6.1</specification-version>
+                    </run-dependency>
+                </dependency>
+                <dependency>
+                    <code-name-base>org.openide.windows</code-name-base>
+                    <build-prerequisite/>
+                    <compile-dependency/>
+                    <run-dependency>
+                        <specification-version>6.75.1</specification-version>
+                    </run-dependency>
+                </dependency>
+            </module-dependencies>
+            <public-packages/>
+        </data>
+    </configuration>
+</project>

+ 1 - 0
jme3-glsl-highlighter/nbproject/suite.properties

@@ -0,0 +1 @@
+suite.dir=${basedir}/..

+ 3 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/Bundle.properties

@@ -0,0 +1,3 @@
+OpenIDE-Module-Display-Category=jMonkeyEngine
+OpenIDE-Module-Name=GLSL Syntax Highlighter
+OpenIDE-Module-Short-Description=Adds support for GLSL

+ 60 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/GlslLanguage.java

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter;
+
+import com.jme3.gde.glsl.highlighter.lexer.GlslLanguageHierarchy;
+import com.jme3.gde.glsl.highlighter.lexer.GlslTokenID;
+import org.netbeans.api.lexer.Language;
+import org.netbeans.modules.csl.spi.DefaultLanguageConfig;
+import org.netbeans.modules.csl.spi.LanguageRegistration;
+
+/**
+ *
+ * @author grizeldi
+ */
+@LanguageRegistration(mimeType = "text/x-glsl")
+public class GlslLanguage extends DefaultLanguageConfig {
+
+    @Override
+    public Language getLexerLanguage() {
+        return new GlslLanguageHierarchy().language();
+    }
+
+    @Override
+    public String getDisplayName() {
+        return "GLSL - OpenGL Shading Language";
+    }
+
+    public static Language<GlslTokenID> getLanguage() {
+        return new GlslLanguageHierarchy().language();
+    }
+}

+ 15 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/layer.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.2//EN" "http://www.netbeans.org/dtds/filesystem-1_2.dtd">
+
+<filesystem>
+    <folder name="Editors">
+        <folder name="text">
+            <folder name="x-glsl">
+                <file name="language.instance">
+                    <attr name="instanceCreate" methodvalue="com.jme3.gde.glsl.highlighter.GlslLanguage.getLanguage"/>
+                    <attr name="instanceOf" stringvalue="org.netbeans.api.lexer.Language"/>
+                </file>
+            </folder>
+        </folder>
+    </folder>
+</filesystem>

+ 486 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslKeywordLibrary.java

@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter.lexer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Brace, yourselves, this file contains every word that means something in
+ * GLSL. Expect about 400 lines of code that just adds strings.
+ *
+ * @author grizeldi
+ */
+class GlslKeywordLibrary {
+
+    public enum KeywordType {
+        KEYWORD, BUILTIN_FUNCTION, BUILTIN_VARIABLE, BASIC_TYPE, UNFINISHED;
+    }
+    private static final List<String> keywords = new ArrayList<>(),
+            builtinFunctions = new ArrayList<>(),
+            builtinVariables = new ArrayList<>(),
+            basicTypes = new ArrayList<>();
+
+    static {
+        //keywords
+        keywords.add("attribute");
+        keywords.add("const");
+        keywords.add("uniform");
+        keywords.add("varying");
+        keywords.add("buffer");
+        keywords.add("shared");
+        keywords.add("coherent");
+        keywords.add("volatile");
+        keywords.add("restrict");
+        keywords.add("readonly");
+        keywords.add("writeonly");
+        keywords.add("atomic_uint");
+        keywords.add("layout");
+        keywords.add("centroid");
+        keywords.add("flat");
+        keywords.add("smooth");
+        keywords.add("noperspective");
+        keywords.add("patch");
+        keywords.add("sample");
+        keywords.add("break");
+        keywords.add("continue");
+        keywords.add("do");
+        keywords.add("for");
+        keywords.add("while");
+        keywords.add("switch");
+        keywords.add("case");
+        keywords.add("default");
+        keywords.add("if");
+        keywords.add("else");
+        keywords.add("subroutine");
+        keywords.add("in");
+        keywords.add("out");
+        keywords.add("inout");
+        keywords.add("void");
+        keywords.add("true");
+        keywords.add("false");
+        keywords.add("invariant");
+        keywords.add("precise");
+        keywords.add("discard");
+        keywords.add("return");
+        //primitives and other types
+        basicTypes.add("float");
+        basicTypes.add("double");
+        basicTypes.add("int");
+        basicTypes.add("bool");
+        basicTypes.add("mat2");
+        basicTypes.add("mat3");
+        basicTypes.add("mat4");
+        basicTypes.add("dmat2");
+        basicTypes.add("dmat3");
+        basicTypes.add("dmat4");
+        basicTypes.add("mat2x2");
+        basicTypes.add("mat2x3");
+        basicTypes.add("mat2x4");
+        basicTypes.add("dmat2x2");
+        basicTypes.add("dmat2x3");
+        basicTypes.add("dmat2x4");
+        basicTypes.add("mat3x2");
+        basicTypes.add("mat3x3");
+        basicTypes.add("mat3x4");
+        basicTypes.add("dmat3x2");
+        basicTypes.add("dmat3x3");
+        basicTypes.add("dmat3x4");
+        basicTypes.add("mat4x2");
+        basicTypes.add("mat4x3");
+        basicTypes.add("mat4x4");
+        basicTypes.add("dmat4x2");
+        basicTypes.add("dmat4x3");
+        basicTypes.add("dmat4x4");
+        basicTypes.add("vec2");
+        basicTypes.add("vec3");
+        basicTypes.add("vec4");
+        basicTypes.add("ivec2");
+        basicTypes.add("ivec3");
+        basicTypes.add("ivec4");
+        basicTypes.add("bvec2");
+        basicTypes.add("bvec3");
+        basicTypes.add("bvec4");
+        basicTypes.add("dvec2");
+        basicTypes.add("dvec3");
+        basicTypes.add("dvec4");
+        basicTypes.add("uint");
+        basicTypes.add("uvec2");
+        basicTypes.add("uvec3");
+        basicTypes.add("uvec4");
+        basicTypes.add("lowp");
+        basicTypes.add("mediump");
+        basicTypes.add("highp");
+        basicTypes.add("precision");
+        basicTypes.add("sampler1D");
+        basicTypes.add("sampler2D");
+        basicTypes.add("sampler3D");
+        basicTypes.add("samplerCube");
+        basicTypes.add("sampler1DShadow");
+        basicTypes.add("sampler2DShadow");
+        basicTypes.add("samplerCubeShadow");
+        basicTypes.add("sampler1DArray");
+        basicTypes.add("sampler2DArray");
+        basicTypes.add("sampler1DArrayShadow");
+        basicTypes.add("sampler2DArrayShadow");
+        basicTypes.add("isampler1D");
+        basicTypes.add("isampler2D");
+        basicTypes.add("isampler3D");
+        basicTypes.add("isamplerCube");
+        basicTypes.add("isampler1DArray");
+        basicTypes.add("isampler2DArray");
+        basicTypes.add("usampler1D");
+        basicTypes.add("usampler2D");
+        basicTypes.add("usampler3D");
+        basicTypes.add("usamplerCube");
+        basicTypes.add("usampler1DArray");
+        basicTypes.add("usampler2DArray");
+        basicTypes.add("sampler2DRect");
+        basicTypes.add("sampler2DRectShadow");
+        basicTypes.add("isampler2DRect");
+        basicTypes.add("usampler2DRect");
+        basicTypes.add("samplerBuffer");
+        basicTypes.add("isamplerBuffer");
+        basicTypes.add("usamplerBuffer");
+        basicTypes.add("sampler2DMS");
+        basicTypes.add("isampler2DMS");
+        basicTypes.add("usampler2DMS");
+        basicTypes.add("sampler2DMSArray");
+        basicTypes.add("isampler2DMSArray");
+        basicTypes.add("usampler2DMSArray");
+        basicTypes.add("samplerCubeArray");
+        basicTypes.add("samplerCubeArrayShadow");
+        basicTypes.add("isamplerCubeArray");
+        basicTypes.add("usamplerCubeArray");
+        basicTypes.add("image1D");
+        basicTypes.add("iimage1D");
+        basicTypes.add("uimage1D");
+        basicTypes.add("image2D");
+        basicTypes.add("iimage2D");
+        basicTypes.add("uimage2D");
+        basicTypes.add("image3D");
+        basicTypes.add("iimage3D");
+        basicTypes.add("uimage3D");
+        basicTypes.add("image2DRect");
+        basicTypes.add("iimage2DRect");
+        basicTypes.add("uimage2DRect");
+        basicTypes.add("imageCube");
+        basicTypes.add("iimageCube");
+        basicTypes.add("uimageCube");
+        basicTypes.add("imageBuffer");
+        basicTypes.add("iimageBuffer");
+        basicTypes.add("uimageBuffer");
+        basicTypes.add("image1DArray");
+        basicTypes.add("iimage1DArray");
+        basicTypes.add("uimage1DArray");
+        basicTypes.add("image2DArray");
+        basicTypes.add("iimage2DArray");
+        basicTypes.add("uimage2DArray");
+        basicTypes.add("imageCubeArray");
+        basicTypes.add("iimageCubeArray");
+        basicTypes.add("uimageCubeArray");
+        basicTypes.add("image2DMS");
+        basicTypes.add("iimage2DMS");
+        basicTypes.add("uimage2DMS");
+        basicTypes.add("image2DMSArray");
+        basicTypes.add("iimage2DMSArray");
+        basicTypes.add("uimage2DMSArray");
+        basicTypes.add("struct");
+        //builtin variables
+        //compute shaders
+        builtinVariables.add("gl_NumWorkGroups");
+        builtinVariables.add("gl_WorkGroupSize");
+        builtinVariables.add("gl_WorkGroupID");
+        builtinVariables.add("gl_LocalInvocationID");
+        builtinVariables.add("gl_GlobalInvocationID");
+        builtinVariables.add("gl_LocalInvocationIndex");
+        //vertex shaders
+        builtinVariables.add("gl_VertexID");
+        builtinVariables.add("gl_InstanceID");
+        //geometry shaders
+        builtinVariables.add("gl_PrimitiveIDIn");
+        builtinVariables.add("gl_Layer");
+        builtinVariables.add("gl_ViewportIndex");
+        //tesselation shaders
+        builtinVariables.add("gl_MaxPatchVertices");
+        builtinVariables.add("gl_PatchVerticesIn");
+        builtinVariables.add("gl_TessLevelOuter");
+        builtinVariables.add("gl_TessLevelInner");
+        builtinVariables.add("gl_TessCoord");
+        //fragment shaders
+        builtinVariables.add("gl_FragCoord");
+        builtinVariables.add("gl_FrontFacing");
+        builtinVariables.add("gl_PointCoord");
+        builtinVariables.add("gl_SampleID");
+        builtinVariables.add("gl_SamplePosition");
+        builtinVariables.add("gl_SampleMaskIn");
+        builtinVariables.add("gl_Layer");
+        builtinVariables.add("gl_ViewportIndex");
+        //general
+        builtinVariables.add("gl_Position");
+        builtinVariables.add("gl_PointSize");
+        builtinVariables.add("gl_ClipDistance");
+        builtinVariables.add("gl_InvocationID");
+        builtinVariables.add("gl_PrimitiveID");
+        //jme variables - this is why we build custom plugins :) (apart from existing being under GPL)
+        builtinVariables.add("inPosition");
+        builtinVariables.add("inNormal");
+        builtinVariables.add("inColor");
+        builtinVariables.add("inTextCoord");
+        builtinVariables.add("g_WorldViewMatrix");
+        builtinVariables.add("g_ProjectionMatrix");
+        builtinVariables.add("g_WorldViewProjectionMatrix");
+        builtinVariables.add("g_NormalMatrix");
+        //builtin functions
+        builtinFunctions.add("radians");
+        builtinFunctions.add("degrees");
+        builtinFunctions.add("sin");
+        builtinFunctions.add("cos");
+        builtinFunctions.add("tan");
+        builtinFunctions.add("asin");
+        builtinFunctions.add("acos");
+        builtinFunctions.add("atan");
+        builtinFunctions.add("sinh");
+        builtinFunctions.add("cosh");
+        builtinFunctions.add("tanh");
+        builtinFunctions.add("asinh");
+        builtinFunctions.add("acosh");
+        builtinFunctions.add("atanh");
+        builtinFunctions.add("pow");
+        builtinFunctions.add("exp");
+        builtinFunctions.add("log");
+        builtinFunctions.add("exp2");
+        builtinFunctions.add("log2");
+        builtinFunctions.add("sqrt");
+        builtinFunctions.add("inversesqrt");
+        builtinFunctions.add("abs");
+        builtinFunctions.add("sign");
+        builtinFunctions.add("floor");
+        builtinFunctions.add("trunc");
+        builtinFunctions.add("round");
+        builtinFunctions.add("roundEven");
+        builtinFunctions.add("ceil");
+        builtinFunctions.add("fract");
+        builtinFunctions.add("mod");
+        builtinFunctions.add("modf");
+        builtinFunctions.add("min");
+        builtinFunctions.add("max");
+        builtinFunctions.add("clamp");
+        builtinFunctions.add("mix");
+        builtinFunctions.add("step");
+        builtinFunctions.add("smoothstep");
+        builtinFunctions.add("isnan");
+        builtinFunctions.add("isinf");
+        builtinFunctions.add("floatBitsToInt");
+        builtinFunctions.add("floatBitsToUInt");
+        builtinFunctions.add("intBitsToFloat");
+        builtinFunctions.add("uintBitsToFloat");
+        builtinFunctions.add("fma");
+        builtinFunctions.add("frexp");
+        builtinFunctions.add("packUnorm2x16");
+        builtinFunctions.add("packSnorm2x16");
+        builtinFunctions.add("packUnorm4x8");
+        builtinFunctions.add("packSnorm4x8");
+        builtinFunctions.add("unpackUnorm2x16");
+        builtinFunctions.add("unpackSnorm2x16");
+        builtinFunctions.add("unpackUnorm4x8");
+        builtinFunctions.add("unpackSnorm4x8");
+        builtinFunctions.add("packDouble2x32");
+        builtinFunctions.add("unpackDouble2x32");
+        builtinFunctions.add("packHalf2x16");
+        builtinFunctions.add("unpackHalf2x16");
+        builtinFunctions.add("length");
+        builtinFunctions.add("distance");
+        builtinFunctions.add("dot");
+        builtinFunctions.add("cross");
+        builtinFunctions.add("normalize");
+        builtinFunctions.add("ftransform");
+        builtinFunctions.add("faceforward");
+        builtinFunctions.add("reflect");
+        builtinFunctions.add("refract");
+        builtinFunctions.add("matrixCompMult");
+        builtinFunctions.add("outerProduct");
+        builtinFunctions.add("transpose");
+        builtinFunctions.add("determinant");
+        builtinFunctions.add("inverse");
+        builtinFunctions.add("lessThan");
+        builtinFunctions.add("lessThanEqual");
+        builtinFunctions.add("greaterThan");
+        builtinFunctions.add("greaterThanEqual");
+        builtinFunctions.add("equal");
+        builtinFunctions.add("notEqual");
+        builtinFunctions.add("any");
+        builtinFunctions.add("all");
+        builtinFunctions.add("not");
+        builtinFunctions.add("uaddCarry");
+        builtinFunctions.add("usubBorrow");
+        builtinFunctions.add("umulExtended");
+        builtinFunctions.add("imulExtended");
+        builtinFunctions.add("bitfieldExtract");
+        builtinFunctions.add("bitfieldInsert");
+        builtinFunctions.add("bitfieldReverse");
+        builtinFunctions.add("bitCount");
+        builtinFunctions.add("findLSB");
+        builtinFunctions.add("findMSB");
+        builtinFunctions.add("textureSize");
+        builtinFunctions.add("textureQueryLod");
+        builtinFunctions.add("textureQueryLevels");
+        builtinFunctions.add("texture");
+        builtinFunctions.add("textureProj");
+        builtinFunctions.add("textureLod");
+        builtinFunctions.add("textureOffset");
+        builtinFunctions.add("texelFetch");
+        builtinFunctions.add("texelFetchOffset");
+        builtinFunctions.add("textureProjOffset");
+        builtinFunctions.add("textureLodOffset");
+        builtinFunctions.add("textureProjLod");
+        builtinFunctions.add("textureProjLodOffset");
+        builtinFunctions.add("textureGrad");
+        builtinFunctions.add("textureGradOffset");
+        builtinFunctions.add("textureProjGrad");
+        builtinFunctions.add("textureProjGradOffset");
+        builtinFunctions.add("textureGather");
+        builtinFunctions.add("textureGatherOffset");
+        builtinFunctions.add("textureGatherOffsets");
+        builtinFunctions.add("texture1D");
+        builtinFunctions.add("texture1DProj");
+        builtinFunctions.add("texture1DLod");
+        builtinFunctions.add("texture1DProjLod");
+        builtinFunctions.add("texture2D");
+        builtinFunctions.add("texture2DProj");
+        builtinFunctions.add("texture2DLod");
+        builtinFunctions.add("texture2DProjLod");
+        builtinFunctions.add("texture3D");
+        builtinFunctions.add("texture3DProj");
+        builtinFunctions.add("texture3DLod");
+        builtinFunctions.add("texture3DProjLod");
+        builtinFunctions.add("textureCube");
+        builtinFunctions.add("textureCubeLod");
+        builtinFunctions.add("shadow1D");
+        builtinFunctions.add("shadow2D");
+        builtinFunctions.add("shadow1DProj");
+        builtinFunctions.add("shadow2DProj");
+        builtinFunctions.add("shadow1DLod");
+        builtinFunctions.add("shadow2DLod");
+        builtinFunctions.add("shadow1DProjLod");
+        builtinFunctions.add("shadow2DProjLod");
+        builtinFunctions.add("atomicCounterIncrement");
+        builtinFunctions.add("atomicCounterDecrement");
+        builtinFunctions.add("atomicCounter");
+        builtinFunctions.add("atomicAdd");
+        builtinFunctions.add("atomicMin");
+        builtinFunctions.add("atomicMax");
+        builtinFunctions.add("atomicAnd");
+        builtinFunctions.add("atomicOr");
+        builtinFunctions.add("atomicXor");
+        builtinFunctions.add("atomicExchange");
+        builtinFunctions.add("atomicCompSwap");
+        builtinFunctions.add("imageSize");
+        builtinFunctions.add("imageLoad");
+        builtinFunctions.add("imageStore");
+        builtinFunctions.add("imageAtomicAdd");
+        builtinFunctions.add("imageAtomicMin");
+        builtinFunctions.add("imageAtomicMax");
+        builtinFunctions.add("imageAtomicAnd");
+        builtinFunctions.add("imageAtomicOr");
+        builtinFunctions.add("imageAtomicXor");
+        builtinFunctions.add("imageAtomicExchange");
+        builtinFunctions.add("imageAtomicCompSwap");
+        builtinFunctions.add("dFdx");
+        builtinFunctions.add("dFdy");
+        builtinFunctions.add("fwidth");
+        builtinFunctions.add("interpolateAtCentroid");
+        builtinFunctions.add("interpolateAtSample");
+        builtinFunctions.add("interpolateAtOffset");
+        builtinFunctions.add("noise1");
+        builtinFunctions.add("noise2");
+        builtinFunctions.add("noise3");
+        builtinFunctions.add("noise4");
+        builtinFunctions.add("EmitStreamVertex");
+        builtinFunctions.add("EndStreamPrimitive");
+        builtinFunctions.add("EmitVertex");
+        builtinFunctions.add("EndPrimitive");
+        builtinFunctions.add("barrier");
+        builtinFunctions.add("memoryBarrier");
+        builtinFunctions.add("memoryBarrierAtomicCounter");
+        builtinFunctions.add("memoryBarrierBuffer");
+        builtinFunctions.add("memoryBarrierShared");
+        builtinFunctions.add("memoryBarrierImage");
+        builtinFunctions.add("groupMemoryBarrier");
+    }
+
+    public static KeywordType lookup(String s) {
+        KeywordType returnType = null;
+        for (String primitive : basicTypes) {
+            if (primitive.startsWith(s)) {
+                if (primitive.equals(s)) {
+                    returnType = KeywordType.BASIC_TYPE;
+                    break;
+                } else {
+                    returnType = KeywordType.UNFINISHED;
+                }
+            }
+        }
+        for (String var : builtinVariables) {
+            if (var.startsWith(s)) {
+                if (var.equals(s)) {
+                    returnType = KeywordType.BUILTIN_VARIABLE;
+                    break;
+                } else {
+                    returnType = KeywordType.UNFINISHED;
+                }
+            }
+        }
+        for (String func : builtinFunctions) {
+            if (func.startsWith(s) && (returnType == KeywordType.UNFINISHED || returnType == null)) {
+                if (func.equals(s)) {
+                    returnType = KeywordType.BUILTIN_FUNCTION;
+                    break;
+                } else {
+                    returnType = KeywordType.UNFINISHED;
+                }
+            }
+        }
+        for (String keyword : keywords) {
+            if (keyword.startsWith(s) && (returnType == KeywordType.UNFINISHED || returnType == null)) {
+                if (keyword.equals(s)) {
+                    returnType = KeywordType.KEYWORD;
+                    break;
+                } else {
+                    returnType = KeywordType.UNFINISHED;
+                }
+            }
+        }
+
+        return returnType;
+    }
+}

+ 61 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslLanguageHierarchy.java

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter.lexer;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import org.netbeans.spi.lexer.LanguageHierarchy;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+
+/**
+ *
+ * @author grizeldi
+ */
+public class GlslLanguageHierarchy extends LanguageHierarchy<GlslTokenID> {
+
+    @Override
+    protected Collection<GlslTokenID> createTokenIds() {
+        return EnumSet.allOf(GlslTokenID.class);
+    }
+
+    @Override
+    protected Lexer<GlslTokenID> createLexer(LexerRestartInfo<GlslTokenID> info) {
+        return new GlslLexer(info);
+    }
+
+    @Override
+    protected String mimeType() {
+        return "text/x-glsl";
+    }
+
+}

+ 258 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslLexer.java

@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter.lexer;
+
+import java.util.logging.Logger;
+import org.netbeans.api.lexer.Token;
+import org.netbeans.spi.lexer.Lexer;
+import org.netbeans.spi.lexer.LexerInput;
+import org.netbeans.spi.lexer.LexerRestartInfo;
+import org.netbeans.spi.lexer.TokenFactory;
+
+/**
+ * Tokenizes the text the user is typing, so we can highlight it as needed.
+ *
+ * @author grizeldi
+ */
+public class GlslLexer implements Lexer<GlslTokenID> {
+
+    private final LexerInput lexerInput;
+    private final TokenFactory tokenFactory;
+    private final Logger log = Logger.getLogger(this.getClass().getCanonicalName());
+
+    private String thisLineSoFar = "";
+
+    public GlslLexer(LexerRestartInfo info) {
+        lexerInput = info.input();
+        tokenFactory = info.tokenFactory();
+    }
+
+    @Override
+    public Token<GlslTokenID> nextToken() {
+        int c;
+        c = lexerInput.read();
+        thisLineSoFar += (char) c;
+        if (isDigit(c)) {
+            while (true) {
+                int next = lexerInput.read();
+                if (!isDigit(next)) {
+                    if (next == '.' || next == 'f' || next == 'F') {
+                        continue;
+                    }
+                    lexerInput.backup(1);
+                    return token(GlslTokenID.NUMBER);
+                }
+            }
+        }
+        switch (c) {
+            case '/':
+                int next = lexerInput.read();
+                if (next == '/') {
+                    //It's an inline comment
+                    readTillNewLine();
+                    return token(GlslTokenID.INLINE_COMMENT);
+                } else if (next == '*') {
+                    while (true) {
+                        int c1 = lexerInput.read();
+                        if (c1 == '*') {
+                            if (lexerInput.read() == '/') {
+                                return token(GlslTokenID.BLOCK_COMMENT);
+                            } else {
+                                lexerInput.backup(1);
+                            }
+                        } else if (c1 == LexerInput.EOF) {
+                            return token(GlslTokenID.BLOCK_COMMENT);
+                        }
+                    }
+                } else {
+                    lexerInput.backup(1);
+                }
+                return token(GlslTokenID.OPERATOR);
+            case '\"':
+            case '\'':
+                //String starts here
+                int previous = c,
+                 starter = c;
+                while (true) {
+                    int now = lexerInput.read();
+
+                    if (now == starter && previous != '\\') {
+                        break;
+                    }
+                    previous = now;
+                }
+                return token(GlslTokenID.STRING);
+            case '#':
+                if (thisLineSoFar.trim().equals("#")) {
+                    //Preprocessor code
+                    readTillNewLine();
+                    return token(GlslTokenID.PREPROCESSOR);
+                }
+                return token(GlslTokenID.OPERATOR);
+            case '|':
+            case '&':
+            case '.':
+            case '>':
+            case '<':
+            case ',':
+            case ';':
+            case ':':
+            case '=':
+            case '+':
+            case '-':
+            case '*':
+            case '%':
+            case '!':
+            case '~':
+            case '^':
+            case '\\':
+                return token(GlslTokenID.OPERATOR);
+            //Those have to be recognized separately for closing bracket recognition
+            case '(':
+                return token(GlslTokenID.LPARENTHESIS);
+            case ')':
+                return token(GlslTokenID.RPARENTHESIS);
+            case '{':
+                return token(GlslTokenID.LBRACKET);
+            case '}':
+                return token(GlslTokenID.RBRACKET);
+            case '[':
+                return token(GlslTokenID.LSQUARE);
+            case ']':
+                return token(GlslTokenID.RSQUARE);
+            case '\n':
+            case '\r':
+                thisLineSoFar = "";
+                return token(GlslTokenID.NEW_LINE);
+            case LexerInput.EOF:
+                return null;
+            default:
+                //Text, gotta look it up the library
+                String word = "" + (char) c;
+                if (GlslKeywordLibrary.lookup(word) != null) {
+                    GlslKeywordLibrary.KeywordType current;
+                    while (true) {
+                        word += (char) lexerInput.read();
+                        current = GlslKeywordLibrary.lookup(word);
+                        if (current != GlslKeywordLibrary.KeywordType.UNFINISHED) {
+                            if (current == null) {
+                                break;
+                            }
+                            char nextChar = (char) lexerInput.read();
+                            lexerInput.backup(1);
+                            if (GlslKeywordLibrary.lookup(word + nextChar) == null /*&& (
+                                    nextChar == ' ' || nextChar == '(' || nextChar == '\n' || nextChar == '\r'
+                                    || nextChar == ';' || nextChar == ',' || nextChar == '.')*/) { //Define here what is allowed to be directly behind a keyword
+                                if (current == GlslKeywordLibrary.KeywordType.BASIC_TYPE && (//What can be behind a primitve
+                                        nextChar == ' ' || nextChar == '(' || nextChar == '\n'
+                                        || nextChar == '\r')) {
+                                    break;
+                                }
+                                if (current == GlslKeywordLibrary.KeywordType.KEYWORD && (//What can be behind a keyword
+                                        nextChar == ' ' || nextChar == '{' || nextChar == ':'
+                                        || nextChar == ';' || nextChar == '(' || nextChar == ')'
+                                        || nextChar == '\n' || nextChar == '\r')) {
+                                    break;
+                                }
+                                if (current == GlslKeywordLibrary.KeywordType.BUILTIN_VARIABLE && (//What can be behind a builtin variable
+                                        nextChar == ';' || nextChar == '.' || nextChar == ' '
+                                        || nextChar == ',' || nextChar == '\n' || nextChar == '\r'
+                                        || nextChar == ')')) {
+                                    break;
+                                }
+                                if (current == GlslKeywordLibrary.KeywordType.BUILTIN_FUNCTION && (//What can be behind a builtin functions
+                                        nextChar == '(' || nextChar == '\n' || nextChar == '\r')) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    if (current == null) {
+                        break;
+                    }
+                    switch (current) {
+                        case BASIC_TYPE:
+                            return token(GlslTokenID.PRIMITIVE);
+                        case KEYWORD:
+                            return token(GlslTokenID.KEYWORD);
+                        case BUILTIN_VARIABLE:
+                            return token(GlslTokenID.BUILTIN_VARIABLE);
+                        case BUILTIN_FUNCTION:
+                            return token(GlslTokenID.BUILTIN_FUNCTION);
+                    }
+                }
+        }
+        return token(GlslTokenID.TEXT);
+    }
+
+    @Override
+    public Object state() {
+        return null;
+    }
+
+    //Honestly, I have no idea what is this.
+    @Override
+    public void release() {
+    }
+
+    private Token<GlslTokenID> token(GlslTokenID id) {
+        return tokenFactory.createToken(id);
+    }
+
+    private boolean isDigit(int c) {
+        switch (c) {
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void readTillNewLine() {
+        while (true) {
+            int in = lexerInput.read();
+            if (in == '\n' || in == '\r' || in == LexerInput.EOF) {
+                lexerInput.backup(1);
+                break;
+            }
+        }
+    }
+}

+ 70 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/lexer/GlslTokenID.java

@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter.lexer;
+
+import org.netbeans.api.lexer.TokenId;
+
+/**
+ *
+ * @author grizeldi
+ */
+public enum GlslTokenID implements TokenId {
+    KEYWORD("keyword"),
+    INLINE_COMMENT("comment"),
+    BLOCK_COMMENT("comment"),
+    STRING("string"),
+    SPACE("whitespace"),
+    NEW_LINE("whitespace"),
+    OPERATOR("operator"),
+    TEXT("default"),
+    PREPROCESSOR("preprocessor"),
+    NUMBER("number"),
+    PRIMITIVE("basictype"),
+    BUILTIN_VARIABLE("builtinvar"),
+    BUILTIN_FUNCTION("builtinfunc"),
+    
+    //Stuff that has to be recognized
+    LBRACKET("operator"), RBRACKET("operator"),
+    LPARENTHESIS("operator"), RPARENTHESIS("operator"),
+    LSQUARE("operator"), RSQUARE("operator");
+
+    private final String category;
+
+    private GlslTokenID(String category) {
+        this.category = category;
+    }
+
+    @Override
+    public String primaryCategory() {
+        return category;
+    }
+}

+ 4 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/FragmentShader.frag

@@ -0,0 +1,4 @@
+
+void main(){
+    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);
+}

+ 163 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/GlslDataObject.java

@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.gde.glsl.highlighter.recognizer;
+
+import java.awt.Image;
+import java.io.IOException;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.MIMEResolver;
+import org.openide.loaders.DataNode;
+import org.openide.loaders.DataObject;
+import org.openide.loaders.DataObjectExistsException;
+import org.openide.loaders.MultiDataObject;
+import org.openide.loaders.MultiFileLoader;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+
+@Messages({
+    "LBL_Glsl_LOADER=OpenGL Shader Language files"
+})
[email protected](
+        displayName = "#LBL_Glsl_LOADER",
+        mimeType = "text/x-glsl",
+        extension = {"frag", "FRAG", "vert", "VERT", "glsllib", "GLSLLIB"}
+)
[email protected](
+        mimeType = "text/x-glsl",
+        displayName = "#LBL_Glsl_LOADER",
+        position = 300
+)
+@ActionReferences({
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.OpenAction"),
+            position = 100,
+            separatorAfter = 200
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "Edit", id = "org.openide.actions.CutAction"),
+            position = 300
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "Edit", id = "org.openide.actions.CopyAction"),
+            position = 400,
+            separatorAfter = 500
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "Edit", id = "org.openide.actions.DeleteAction"),
+            position = 600
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.RenameAction"),
+            position = 700,
+            separatorAfter = 800
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.SaveAsTemplateAction"),
+            position = 900,
+            separatorAfter = 1000
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.FileSystemAction"),
+            position = 1100,
+            separatorAfter = 1200
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.ToolsAction"),
+            position = 1300
+    )
+    ,
+    @ActionReference(
+            path = "Loaders/text/x-glsl/Actions",
+            id = @ActionID(category = "System", id = "org.openide.actions.PropertiesAction"),
+            position = 1400
+    )
+})
+public class GlslDataObject extends MultiDataObject {
+
+    public GlslDataObject(FileObject pf, MultiFileLoader loader) throws DataObjectExistsException, IOException {
+        super(pf, loader);
+        registerEditor("text/x-glsl", false);
+    }
+
+    @Override
+    protected int associateLookup() {
+        return 1;
+    }
+
+    @Override
+    protected Node createNodeDelegate() {
+        return new GlslNode(getLookup());
+    }
+
+    //We need a custom node in order to get a dynamic icon for some reason
+    private class GlslNode extends DataNode {
+
+        private final Image fragIcon = ImageUtilities.loadImage("com/jme3/gde/glsl/highlighter/recognizer/fragIcon.png"),
+                vertIcon = ImageUtilities.loadImage("com/jme3/gde/glsl/highlighter/recognizer/vertIcon.png"),
+                defaultIcon = ImageUtilities.loadImage("org/netbeans/modules/java/resources/annotation_file.png");
+
+        public GlslNode(Lookup lookup) {
+            super(GlslDataObject.this, Children.LEAF, lookup);
+        }
+
+        @Override
+        public Image getIcon(int type) {
+            if (getPrimaryFile().getExt().toLowerCase().equals("frag")) {
+                return fragIcon;
+            } else if (getPrimaryFile().getExt().toLowerCase().equals("vert")) {
+                return vertIcon;
+            }
+            return defaultIcon;
+        }
+    }
+}

+ 7 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/VertexShader.vert

@@ -0,0 +1,7 @@
+uniform mat4 g_WorldViewProjectionMatrix;
+
+attribute vec3 inPosition;
+
+void main(){
+    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
+}

BIN
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/fragIcon.png


+ 41 - 0
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/package-info.java

@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2018 jMonkeyEngine
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+@TemplateRegistrations({
+    @TemplateRegistration(folder = "GLSL", displayName = "Fragment Shader",
+            iconBase = "com/jme3/gde/glsl/highlighter/recognizer/fragIcon.png", content = "FragmentShader.frag"),
+    @TemplateRegistration(folder = "GLSL", displayName = "Vertex Shader",
+            iconBase = "com/jme3/gde/glsl/highlighter/recognizer/vertIcon.png", content = "VertexShader.vert")
+})
+package com.jme3.gde.glsl.highlighter.recognizer;
+
+import org.netbeans.api.templates.TemplateRegistration;
+import org.netbeans.api.templates.TemplateRegistrations;

BIN
jme3-glsl-highlighter/src/com/jme3/gde/glsl/highlighter/recognizer/vertIcon.png


+ 7 - 5
nbproject/project.properties

@@ -1,4 +1,4 @@
-#Fri, 25 Mar 2016 09:25:21 +0100
+#Mon, 15 Jan 2018 18:51:47 +0100
 app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif
 #same as ${branding.token}
 app.name=jmonkeyplatform
@@ -7,10 +7,10 @@ app.description=A complete 3D game development suite written purely in Java.
 app.categories=Development,Graphics,IDE,3DGraphics,Java
 app.icon.icns=jmonkeyplatform.icns
 #version name used for application and settings folder, no spaces!
-app.version=3.1.0-alpha3
+app.version=3.2.0-SNAPSHOT
 #version number used for plugins, only 3 numbers (e.g. 3.1.3)
-plugins.version=3.1.0
-nbm.revision=0
+plugins.version=3.2.0
+nbm.revision=1803
 #command line args
 run.args.extra=-J-Dsun.java2d.dpiaware\=true -J-Dapple.laf.useScreenMenuBar\=true -J-Dawt.useSystemAAFontSettings\=lcd -J-Dswing.aatext\=true -J-Xmx512m -J-XX\:MaxDirectMemorySize\=2048m -J-Dsun.zip.disableMemoryMapping\=true -J-Dapple.awt.graphics.UseQuartz\=true -J-Dsun.java2d.noddraw\=true
 auxiliary.org-netbeans-modules-apisupport-installer.license-file=license-jme.txt
@@ -53,7 +53,8 @@ modules=\
     ${project.com.jme3.gde.nmgen}:\
     ${project.com.jme3.gde.docs}:\
     ${project.org.jme3.netbeans.plaf.darkmonkey}:\
-    ${project.com.jme3.gde.ios}
+    ${project.com.jme3.gde.ios}:\
+    ${project.com.jme3.gde.glsl.highlighter}
 project.com.jme3.gde.android=jme3-android
 project.com.jme3.gde.angelfont=jme3-angelfont
 project.com.jme3.gde.blender=jme3-blender
@@ -68,6 +69,7 @@ project.com.jme3.gde.core=jme3-core
 project.com.jme3.gde.core.baselibs=jme3-core-baselibs
 project.com.jme3.gde.core.libraries=jme3-core-libraries
 project.com.jme3.gde.core.updatecenters=jme3-core-updatecenters
+project.com.jme3.gde.glsl.highlighter=jme3-glsl-highlighter
 project.com.jme3.gde.gui=jme3-gui
 project.com.jme3.gde.ios=jme3-ios
 project.com.jme3.gde.lwjgl.applet=jme3-lwjgl-applet