Skip to content

Commit 5ee76c0

Browse files
committed
реализован текстовой редактор шейдеров
1 parent 6fbe794 commit 5ee76c0

File tree

11 files changed

+289
-6
lines changed

11 files changed

+289
-6
lines changed

build-native.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
name="jME3-SpaceShift-Editor"
118118
mainClass="com.ss.editor.Starter"
119119
toolkit="fx"
120-
version="0.4.0"
120+
version="0.4.5"
121121
/>
122122

123123
<mkdir dir="build/classes/META-INF"/>
@@ -130,7 +130,7 @@
130130
<manifest>
131131
<attribute name="Implementation-Vendor" value="spaceshift.ru"/>
132132
<attribute name="Implementation-Title" value="jME3 SpaceShift Editor"/>
133-
<attribute name="Implementation-Version" value="0.4.0"/>
133+
<attribute name="Implementation-Version" value="0.4.5"/>
134134
</manifest>
135135
</fx:jar>
136136

build/package/linux/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: jme3-spaceshift-editor
2-
Version: 0.3.7
2+
Version: 0.4.5
33
Section: tool
44
Maintainer: spaceshift.ru <[email protected]>
55
Priority: optional

libs/richtextfx-fat-0.6.10.jar

660 KB
Binary file not shown.

resources/messages/messages.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ EmptyFileCreatorTitle=Create empty file
120120

121121
ImageViewerEditorName=View image
122122

123-
NodeDialogButtonOk=Создать
124-
NodeDialogButtonCancel=Отменить
123+
NodeDialogButtonOk=Create
124+
NodeDialogButtonCancel=Cancel
125125

126126
CreateSkyDialogTitle=Create sky
127127
CreateSkyDialogSkyTypeSingle=Single texture

resources/ui/css/custom_classes.css

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,42 @@
232232

233233
.model-param-control {
234234
-fx-alignment: center-left;
235+
}
236+
237+
.plain-code {
238+
-fx-fill: white;
239+
}
240+
.keyword {
241+
-fx-fill: #f92647;
242+
-fx-font-weight: bold;
243+
}
244+
.value-type {
245+
-fx-fill: #66d9ef;
246+
-fx-font-weight: bold;
247+
}
248+
.semicolon {
249+
-fx-fill: white;
250+
-fx-font-weight: bold;
251+
}
252+
.paren {
253+
-fx-fill: white;
254+
-fx-font-weight: bold;
255+
}
256+
.bracket {
257+
-fx-fill: white;
258+
-fx-font-weight: bold;
259+
}
260+
.brace {
261+
-fx-fill: white;
262+
-fx-font-weight: bold;
263+
}
264+
.string {
265+
-fx-fill: #d4db68;
266+
}
267+
.comment {
268+
-fx-fill: #b2ae94;
269+
}
270+
271+
.paragraph-box:has-caret {
272+
-fx-background-color: #f2f9fc;
235273
}

resources/ui/css/external.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
.code-area {
3+
4+
}

src/com/ss/editor/FileExtensions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,8 @@ public interface FileExtensions {
2323
public static final String IMAGE_DDS = "dds";
2424
public static final String IMAGE_HDR = "hdr";
2525

26+
public static final String GLSL_VERTEX = "vert";
27+
public static final String GLSL_FRAGMENT = "frag";
28+
2629
public static final String BLENDER = "blend";
2730
}

src/com/ss/editor/config/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public abstract class Config {
2020
public static final String CONFIG_RESOURCE_PATH = "/com/ss/editor/config/config.xml";
2121

2222
public static final String TITLE = "jME3 SpaceShift Editor";
23-
public static final String VERSION = "v.0.4.0";
23+
public static final String VERSION = "v.0.4.5";
2424

2525
public static final String SS_FOLDER_IN_USER_HOME = ".jme3-spaceshift-editor";
2626

src/com/ss/editor/ui/component/editor/EditorRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.ss.editor.ui.component.editor;
22

3+
import com.ss.editor.ui.component.editor.impl.GLSLFileEditor;
34
import com.ss.editor.ui.component.editor.impl.ImageViewerEditor;
45
import com.ss.editor.ui.component.editor.impl.TextFileEditor;
56
import com.ss.editor.ui.component.editor.impl.material.MaterialFileEditor;
@@ -54,6 +55,7 @@ private void loadDescriptions() {
5455
addDescription(MaterialFileEditor.DESCRIPTION);
5556
addDescription(ModelFileEditor.DESCRIPTION);
5657
addDescription(ImageViewerEditor.DESCRIPTION);
58+
addDescription(GLSLFileEditor.DESCRIPTION);
5759
}
5860

5961
/**
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
package com.ss.editor.ui.component.editor.impl;
2+
3+
import com.ss.editor.FileExtensions;
4+
import com.ss.editor.ui.component.editor.EditorDescription;
5+
import com.ss.editor.ui.css.CSSClasses;
6+
import com.ss.editor.ui.css.CSSIds;
7+
8+
import org.fxmisc.richtext.CodeArea;
9+
import org.fxmisc.richtext.StyleSpans;
10+
import org.fxmisc.richtext.StyleSpansBuilder;
11+
12+
import java.io.IOException;
13+
import java.io.PrintWriter;
14+
import java.nio.file.Files;
15+
import java.nio.file.Path;
16+
import java.util.Collection;
17+
import java.util.regex.Matcher;
18+
import java.util.regex.Pattern;
19+
20+
import javafx.scene.layout.HBox;
21+
import javafx.scene.layout.VBox;
22+
import rlib.ui.util.FXUtils;
23+
import rlib.util.FileUtils;
24+
import rlib.util.StringUtils;
25+
26+
import static java.util.Collections.emptyList;
27+
import static java.util.Collections.singleton;
28+
29+
/**
30+
* Реализация редактора GLSL файлов.
31+
*
32+
* @author Ronn
33+
*/
34+
public class GLSLFileEditor extends AbstractFileEditor<VBox> {
35+
36+
public static final EditorDescription DESCRIPTION = new EditorDescription();
37+
38+
static {
39+
DESCRIPTION.setConstructor(GLSLFileEditor::new);
40+
DESCRIPTION.setEditorName("GLSL Editor");
41+
DESCRIPTION.addExtension(FileExtensions.GLSL_FRAGMENT);
42+
DESCRIPTION.addExtension(FileExtensions.GLSL_VERTEX);
43+
}
44+
45+
private static final String[] KEYWORDS = new String[]{
46+
"define", "undef", "if", "ifdef", "ifndef",
47+
"else", "elif", "endif", "error", "pragma",
48+
"extension", "version", "line", "attribute", "const",
49+
"uniform", "varying", "layout", "centroid", "flat",
50+
"smooth", "noperspective", "patch", "sample", "break",
51+
"continue", "do", "for", "while", "switch",
52+
"case", "default", "if", "subroutine", "in", "out", "inout",
53+
"void", "true", "false", "invariant", "discard", "return", "struct"
54+
};
55+
56+
private static final String[] VALUE_TYPES = new String[]{
57+
"float", "double", "int", "bool", "mat2", "mat3", "mat4", "uint", "uvec2", "uvec3", "uvec4",
58+
"sampler1D", "sampler2D", "sampler3D", "samplerCube", "vec2", "vec3", "vec4"
59+
};
60+
61+
private static final String KEYWORD_PATTERN = "\\b(" + String.join("|", KEYWORDS) + ")\\b";
62+
private static final String VALUE_TYPE_PATTERN = "\\b(" + String.join("|", VALUE_TYPES) + ")\\b";
63+
private static final String PAREN_PATTERN = "\\(|\\)";
64+
private static final String BRACE_PATTERN = "\\{|\\}";
65+
private static final String BRACKET_PATTERN = "\\[|\\]";
66+
private static final String SEMICOLON_PATTERN = "\\;";
67+
private static final String STRING_PATTERN = "\"([^\"\\\\]|\\\\.)*\"";
68+
private static final String COMMENT_PATTERN = "//[^\n]*" + "|" + "/\\*(.|\\R)*?\\*/";
69+
70+
private static final Pattern PATTERN = Pattern.compile(
71+
"(?<KEYWORD>" + KEYWORD_PATTERN + ")"
72+
+ "|(?<VALUETYPE>" + VALUE_TYPE_PATTERN + ")"
73+
+ "|(?<PAREN>" + PAREN_PATTERN + ")"
74+
+ "|(?<BRACE>" + BRACE_PATTERN + ")"
75+
+ "|(?<BRACKET>" + BRACKET_PATTERN + ")"
76+
+ "|(?<SEMICOLON>" + SEMICOLON_PATTERN + ")"
77+
+ "|(?<STRING>" + STRING_PATTERN + ")"
78+
+ "|(?<COMMENT>" + COMMENT_PATTERN + ")"
79+
);
80+
81+
private static StyleSpans<Collection<String>> computeHighlighting(final String text) {
82+
83+
final Matcher matcher = PATTERN.matcher(text);
84+
final StyleSpansBuilder<Collection<String>> spansBuilder = new StyleSpansBuilder<>();
85+
86+
int lastKwEnd = 0;
87+
88+
while (matcher.find()) {
89+
90+
String styleClass = matcher.group("KEYWORD") != null ? "keyword" : null;
91+
92+
if(styleClass == null ) {
93+
styleClass = matcher.group("VALUETYPE") != null ? "value-type" : null;
94+
}
95+
96+
if(styleClass == null ) {
97+
styleClass = matcher.group("PAREN") != null ? "paren" : null;
98+
}
99+
100+
if(styleClass == null ) {
101+
styleClass = matcher.group("BRACE") != null ? "brace" : null;
102+
}
103+
104+
if(styleClass == null ) {
105+
styleClass = matcher.group("BRACKET") != null ? "bracket" : null;
106+
}
107+
108+
if(styleClass == null ) {
109+
styleClass = matcher.group("SEMICOLON") != null ? "semicolon" : null;
110+
}
111+
112+
if(styleClass == null ) {
113+
styleClass = matcher.group("STRING") != null ? "string" : null;
114+
}
115+
116+
if(styleClass == null ) {
117+
styleClass = matcher.group("COMMENT") != null ? "comment" : null;
118+
}
119+
120+
assert styleClass != null;
121+
122+
spansBuilder.add(singleton("plain-code"), matcher.start() - lastKwEnd);
123+
spansBuilder.add(singleton(styleClass), matcher.end() - matcher.start());
124+
125+
lastKwEnd = matcher.end();
126+
}
127+
128+
spansBuilder.add(emptyList(), text.length() - lastKwEnd);
129+
130+
return spansBuilder.create();
131+
}
132+
133+
/**
134+
* Контент на момент открытия документа.
135+
*/
136+
private String originalContent;
137+
138+
/**
139+
* Область для редактирования кода.
140+
*/
141+
private CodeArea codeArea;
142+
143+
@Override
144+
protected VBox createRoot() {
145+
return new VBox();
146+
}
147+
148+
@Override
149+
protected void createContent(final VBox root) {
150+
151+
codeArea = new CodeArea();
152+
codeArea.setId(CSSIds.TEXT_EDITOR_TEXT_AREA);
153+
//codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
154+
codeArea.richChanges().subscribe(change -> codeArea.setStyleSpans(0, computeHighlighting(codeArea.getText())));
155+
codeArea.textProperty().addListener((observable, oldValue, newValue) -> updateDirty(newValue));
156+
157+
FXUtils.addToPane(codeArea, root);
158+
FXUtils.addClassTo(codeArea, CSSClasses.MAIN_FONT_13);
159+
FXUtils.bindFixedSize(codeArea, root.widthProperty(), root.heightProperty());
160+
}
161+
162+
/**
163+
* Обновление состояния измененности.
164+
*/
165+
private void updateDirty(final String newContent) {
166+
setDirty(!getOriginalContent().equals(newContent));
167+
}
168+
169+
@Override
170+
protected boolean needToolbar() {
171+
return true;
172+
}
173+
174+
@Override
175+
protected void createToolbar(final HBox container) {
176+
super.createToolbar(container);
177+
FXUtils.addToPane(createSaveAction(), container);
178+
}
179+
180+
/**
181+
* @return область для редактирования кода.
182+
*/
183+
private CodeArea getCodeArea() {
184+
return codeArea;
185+
}
186+
187+
@Override
188+
public void openFile(final Path file) {
189+
super.openFile(file);
190+
191+
final byte[] content = FileUtils.getContent(file);
192+
193+
if (content == null) {
194+
setOriginalContent(StringUtils.EMPTY);
195+
} else {
196+
setOriginalContent(new String(content));
197+
}
198+
199+
final CodeArea codeArea = getCodeArea();
200+
codeArea.replaceText(0, 0, getOriginalContent());
201+
}
202+
203+
/**
204+
* @return контент на момент открытия документа.
205+
*/
206+
public String getOriginalContent() {
207+
return originalContent;
208+
}
209+
210+
/**
211+
* @param originalContent контент на момент открытия документа.
212+
*/
213+
public void setOriginalContent(final String originalContent) {
214+
this.originalContent = originalContent;
215+
}
216+
217+
@Override
218+
public void doSave() {
219+
super.doSave();
220+
221+
final CodeArea codeArea = getCodeArea();
222+
final String newContent = codeArea.getText();
223+
224+
try (final PrintWriter out = new PrintWriter(Files.newOutputStream(getEditFile()))) {
225+
out.print(newContent);
226+
} catch (final IOException e) {
227+
LOGGER.warning(this, e);
228+
}
229+
230+
setOriginalContent(newContent);
231+
updateDirty(newContent);
232+
notifyFileChanged();
233+
}
234+
}

0 commit comments

Comments
 (0)