Effects support added
This commit is contained in:
parent
d4c138cf33
commit
11582fd69d
14 changed files with 545 additions and 508 deletions
2
pom.xml
2
pom.xml
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
<groupId>loper</groupId>
|
<groupId>loper</groupId>
|
||||||
<artifactId>LogiLed</artifactId>
|
<artifactId>LogiLed</artifactId>
|
||||||
<version>0.1-SNAPSHOT</version>
|
<version>0.2-SNAPSHOT</version>
|
||||||
|
|
||||||
<!-- <url></url> -->
|
<!-- <url></url> -->
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
@ -58,13 +59,12 @@ public class EffectsController implements Initializable {
|
||||||
mainSlideInfoLbl.setVisible(false);
|
mainSlideInfoLbl.setVisible(false);
|
||||||
break;
|
break;
|
||||||
case "constRMI":
|
case "constRMI":
|
||||||
case "breathRMI":
|
|
||||||
mainClrPkr.setVisible(true);
|
mainClrPkr.setVisible(true);
|
||||||
mainSlide.setVisible(false);
|
mainSlide.setVisible(false);
|
||||||
mainSlideInfoLbl.setVisible(false);
|
mainSlideInfoLbl.setVisible(false);
|
||||||
break;
|
break;
|
||||||
case "cycleRMI":
|
case "circlesOnPressRMI":
|
||||||
mainClrPkr.setVisible(false);
|
mainClrPkr.setVisible(true);
|
||||||
mainSlide.setVisible(true);
|
mainSlide.setVisible(true);
|
||||||
mainSlideInfoLbl.setVisible(true);
|
mainSlideInfoLbl.setVisible(true);
|
||||||
mainSlide.setMin(20.0);
|
mainSlide.setMin(20.0);
|
||||||
|
@ -73,7 +73,7 @@ public class EffectsController implements Initializable {
|
||||||
mainSlide.setBlockIncrement(10.0);
|
mainSlide.setBlockIncrement(10.0);
|
||||||
mainSlide.setValue(20.0);
|
mainSlide.setValue(20.0);
|
||||||
break;
|
break;
|
||||||
case "circlesOnPressRMI":
|
case "breathRMI":
|
||||||
mainClrPkr.setVisible(true);
|
mainClrPkr.setVisible(true);
|
||||||
mainSlide.setVisible(true);
|
mainSlide.setVisible(true);
|
||||||
mainSlideInfoLbl.setVisible(true);
|
mainSlideInfoLbl.setVisible(true);
|
||||||
|
@ -83,6 +83,7 @@ public class EffectsController implements Initializable {
|
||||||
mainSlide.setBlockIncrement(100.0);
|
mainSlide.setBlockIncrement(100.0);
|
||||||
mainSlide.setValue(1000.0);
|
mainSlide.setValue(1000.0);
|
||||||
break;
|
break;
|
||||||
|
case "cycleRMI":
|
||||||
case "hWaveFrwRMI":
|
case "hWaveFrwRMI":
|
||||||
case "vWaveFrwRMI":
|
case "vWaveFrwRMI":
|
||||||
case "cntrToEdgWaveRMI":
|
case "cntrToEdgWaveRMI":
|
||||||
|
@ -101,49 +102,83 @@ public class EffectsController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEffect(){
|
public HashMap<String, Byte> getEffect(){
|
||||||
final RadioMenuItem item = (RadioMenuItem) effectsToggleGrp.getSelectedToggle();
|
final RadioMenuItem item = (RadioMenuItem) effectsToggleGrp.getSelectedToggle();
|
||||||
/*
|
|
||||||
HashMap<LoEffects, byte[]> effectsSet = new HashMap<>();
|
final HashMap<String, Byte> effectsSet = new HashMap<>();
|
||||||
byte[] meta;
|
|
||||||
|
final byte red = (byte) (mainClrPkr.getValue().getRed()*255);
|
||||||
|
final byte green = (byte) (mainClrPkr.getValue().getGreen()*255);
|
||||||
|
final byte blue = (byte) (mainClrPkr.getValue().getBlue()*255);
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
|
||||||
|
buffer.putLong((long) mainSlide.getValue());
|
||||||
|
byte[] a = buffer.array();
|
||||||
|
byte valHigh = a[6]; // E.g. 1000 = 0x03 0xe8; high = 0x03, low = 0xe8
|
||||||
|
byte valLow = a[7];
|
||||||
|
|
||||||
switch (item.getId()){
|
switch (item.getId()){
|
||||||
case "disRMI":
|
case "disRMI":
|
||||||
effectsSet.put(LoEffects.DISABLE, null);
|
effectsSet.put("EFFECT", LoEffects.DISABLE.getValue());
|
||||||
break;
|
break;
|
||||||
case "constRMI":
|
case "constRMI":
|
||||||
effectsSet.put(LoEffects.CONSTANT_COLOR, );
|
effectsSet.put("EFFECT", LoEffects.CONSTANT_COLOR.getValue());
|
||||||
|
effectsSet.put("RED", red);
|
||||||
|
effectsSet.put("GREEN", green);
|
||||||
|
effectsSet.put("BLUE", blue);
|
||||||
break;
|
break;
|
||||||
case "breathRMI":
|
case "breathRMI":
|
||||||
effectsSet.put(LoEffects.BREATH, );
|
effectsSet.put("EFFECT", LoEffects.BREATH.getValue());
|
||||||
break;
|
effectsSet.put("RED", red);
|
||||||
case "cycleRMI":
|
effectsSet.put("GREEN", green);
|
||||||
effectsSet.put(LoEffects.CYCLE, );
|
effectsSet.put("BLUE", blue);
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "circlesOnPressRMI":
|
case "circlesOnPressRMI":
|
||||||
effectsSet.put(LoEffects.CIRCLES_ON_PRESS, );
|
effectsSet.put("EFFECT", LoEffects.CIRCLES_ON_PRESS.getValue());
|
||||||
|
effectsSet.put("RED", red);
|
||||||
|
effectsSet.put("GREEN", green);
|
||||||
|
effectsSet.put("BLUE", blue);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
|
break;
|
||||||
|
case "cycleRMI":
|
||||||
|
effectsSet.put("EFFECT", LoEffects.CYCLE.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "hWaveFrwRMI":
|
case "hWaveFrwRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_HORIZONTAL_FRW, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_HORIZONTAL_FRW.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "vWaveFrwRMI":
|
case "vWaveFrwRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_VERTICAL_FRW, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_VERTICAL_FRW.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "cntrToEdgWaveRMI":
|
case "cntrToEdgWaveRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_CENTER_TO_EDGE, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_CENTER_TO_EDGE.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "hWaveBkwRMI":
|
case "hWaveBkwRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_HORIZONTAL_BKW, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_HORIZONTAL_BKW.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "vWaveBkwRMI":
|
case "vWaveBkwRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_VERTICAL_BKW, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_VERTICAL_BKW.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
case "edgToCntrWaveRMI":
|
case "edgToCntrWaveRMI":
|
||||||
effectsSet.put(LoEffects.WAVE_EDGE_TO_CENTER, );
|
effectsSet.put("EFFECT", LoEffects.WAVE_EDGE_TO_CENTER.getValue());
|
||||||
|
effectsSet.put("TIME_HIGH", valHigh);
|
||||||
|
effectsSet.put("TIME_LOW", valLow);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
//System.out.println(LoEffects.DISABLE.getValue());
|
return effectsSet;
|
||||||
return item.getId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,227 +0,0 @@
|
||||||
package logiled.Controllers;
|
|
||||||
// TODO: rewrite to ENUM
|
|
||||||
class LoCodepage {
|
|
||||||
static byte getCode(String id){
|
|
||||||
switch (id){
|
|
||||||
case "l_game":
|
|
||||||
return 0x2;
|
|
||||||
case "l_caps":
|
|
||||||
return 0x3;
|
|
||||||
case "k_a":
|
|
||||||
return 0x4;
|
|
||||||
case "k_b":
|
|
||||||
return 0x5;
|
|
||||||
case "k_c":
|
|
||||||
return 0x6;
|
|
||||||
case "k_d":
|
|
||||||
return 0x7;
|
|
||||||
case "k_e":
|
|
||||||
return 0x8;
|
|
||||||
case "k_f":
|
|
||||||
return 0x9;
|
|
||||||
case "k_g":
|
|
||||||
return 0xA;
|
|
||||||
case "k_h":
|
|
||||||
return 0xB;
|
|
||||||
case "k_i":
|
|
||||||
return 0xC;
|
|
||||||
case "k_j":
|
|
||||||
return 0xD;
|
|
||||||
case "k_k":
|
|
||||||
return 0xE;
|
|
||||||
case "k_l":
|
|
||||||
return 0xF;
|
|
||||||
case "k_m":
|
|
||||||
return 0x10;
|
|
||||||
case "k_n":
|
|
||||||
return 0x11;
|
|
||||||
case "k_o":
|
|
||||||
return 0x12;
|
|
||||||
case "k_p":
|
|
||||||
return 0x13;
|
|
||||||
case "k_q":
|
|
||||||
return 0x14;
|
|
||||||
case "k_r":
|
|
||||||
return 0x15;
|
|
||||||
case "k_s":
|
|
||||||
return 0x16;
|
|
||||||
case "k_t":
|
|
||||||
return 0x17;
|
|
||||||
case "k_u":
|
|
||||||
return 0x18;
|
|
||||||
case "k_v":
|
|
||||||
return 0x19;
|
|
||||||
case "k_w":
|
|
||||||
return 0x1A;
|
|
||||||
case "k_x":
|
|
||||||
return 0x1B;
|
|
||||||
case "k_y":
|
|
||||||
return 0x1C;
|
|
||||||
case "k_z":
|
|
||||||
return 0x1D;
|
|
||||||
case "k_1":
|
|
||||||
return 0x1E;
|
|
||||||
case "k_2":
|
|
||||||
return 0x1F;
|
|
||||||
case "k_3":
|
|
||||||
return 0x20;
|
|
||||||
case "k_4":
|
|
||||||
return 0x21;
|
|
||||||
case "k_5":
|
|
||||||
return 0x22;
|
|
||||||
case "k_6":
|
|
||||||
return 0x23;
|
|
||||||
case "k_7":
|
|
||||||
return 0x24;
|
|
||||||
case "k_8":
|
|
||||||
return 0x25;
|
|
||||||
case "k_9":
|
|
||||||
return 0x26;
|
|
||||||
case "k_0":
|
|
||||||
return 0x27;
|
|
||||||
case "k_enter":
|
|
||||||
return 0x28;
|
|
||||||
case "k_esc":
|
|
||||||
return 0x29;
|
|
||||||
case "k_backspace":
|
|
||||||
return 0x2a;
|
|
||||||
case "k_tab":
|
|
||||||
return 0x2b;
|
|
||||||
case "k_space":
|
|
||||||
return 0x2c;
|
|
||||||
case "k_dash":
|
|
||||||
return 0x2d;
|
|
||||||
case "k_equal":
|
|
||||||
return 0x2e;
|
|
||||||
case "k_bracket_open":
|
|
||||||
return 0x2f;
|
|
||||||
case "k_bracket_close":
|
|
||||||
return 0x30;
|
|
||||||
// nothing for 0x31
|
|
||||||
case "k_backslash":
|
|
||||||
return 0x32; // (ISO version only?)
|
|
||||||
case "k_semicolon":
|
|
||||||
return 0x33;
|
|
||||||
case "k_quotation":
|
|
||||||
return 0x34;
|
|
||||||
case "k_tilde":
|
|
||||||
return 0x35;
|
|
||||||
case "k_comma":
|
|
||||||
return 0x36;
|
|
||||||
case "k_dot":
|
|
||||||
return 0x37;
|
|
||||||
case "k_shash":
|
|
||||||
return 0x38;
|
|
||||||
case "k_caps":
|
|
||||||
return 0x39;
|
|
||||||
case "k_f1":
|
|
||||||
return 0x3a;
|
|
||||||
case "k_f2":
|
|
||||||
return 0x3b;
|
|
||||||
case "k_f3":
|
|
||||||
return 0x3c;
|
|
||||||
case "k_f4":
|
|
||||||
return 0x3d;
|
|
||||||
case "k_f5":
|
|
||||||
return 0x3e;
|
|
||||||
case "k_f6":
|
|
||||||
return 0x3f;
|
|
||||||
case "k_f7":
|
|
||||||
return 0x40;
|
|
||||||
case "k_f8":
|
|
||||||
return 0x41;
|
|
||||||
case "k_f9":
|
|
||||||
return 0x42;
|
|
||||||
case "k_f10":
|
|
||||||
return 0x43;
|
|
||||||
case "k_f11":
|
|
||||||
return 0x44;
|
|
||||||
case "k_f12":
|
|
||||||
return 0x45;
|
|
||||||
case "k_prtscr":
|
|
||||||
return 0x46;
|
|
||||||
case "k_scrl":
|
|
||||||
return 0x47;
|
|
||||||
case "k_pause":
|
|
||||||
return 0x48;
|
|
||||||
case "k_ins":
|
|
||||||
return 0x49;
|
|
||||||
case "k_home":
|
|
||||||
return 0x4a;
|
|
||||||
case "k_pg_up":
|
|
||||||
return 0x4b;
|
|
||||||
case "k_del":
|
|
||||||
return 0x4c;
|
|
||||||
case "k_end":
|
|
||||||
return 0x4d;
|
|
||||||
case "k_pg_dn":
|
|
||||||
return 0x4e;
|
|
||||||
case "k_arr_right":
|
|
||||||
return 0x4f;
|
|
||||||
case "k_arr_left":
|
|
||||||
return 0x50;
|
|
||||||
case "k_arr_down":
|
|
||||||
return 0x51;
|
|
||||||
case "k_arr_up":
|
|
||||||
return 0x52;
|
|
||||||
case "k_num":
|
|
||||||
return 0x53;
|
|
||||||
case "k_num_slash":
|
|
||||||
return 0x54;
|
|
||||||
case "k_num_asterisk":
|
|
||||||
return 0x55;
|
|
||||||
case "k_num_minus":
|
|
||||||
return 0x56;
|
|
||||||
case "k_num_plus":
|
|
||||||
return 0x57;
|
|
||||||
/* not confirmed */
|
|
||||||
case "k_num_enter":
|
|
||||||
return 0x58;
|
|
||||||
case "k_num_1":
|
|
||||||
return 0x59;
|
|
||||||
case "k_num_2":
|
|
||||||
return 0x5a;
|
|
||||||
case "k_num_3":
|
|
||||||
return 0x5b;
|
|
||||||
case "k_num_4":
|
|
||||||
return 0x5c;
|
|
||||||
case "k_num_5":
|
|
||||||
return 0x5d;
|
|
||||||
case "k_num_6":
|
|
||||||
return 0x5e;
|
|
||||||
case "k_num_7":
|
|
||||||
return 0x5f;
|
|
||||||
case "k_num_8":
|
|
||||||
return 0x60;
|
|
||||||
case "k_num_9":
|
|
||||||
return 0x61;
|
|
||||||
case "k_num_0":
|
|
||||||
return 0x62;
|
|
||||||
case "k_num_period":
|
|
||||||
return 0x63;
|
|
||||||
/*---------------*/
|
|
||||||
// nothing for 0x64 (ISO version)
|
|
||||||
case "k_menu":
|
|
||||||
return 0x65;
|
|
||||||
|
|
||||||
case "k_l_ctrl":
|
|
||||||
return (byte) 0xe0;
|
|
||||||
case "k_l_shift":
|
|
||||||
return (byte) 0xe1;
|
|
||||||
case "k_l_alt":
|
|
||||||
return (byte) 0xe2;
|
|
||||||
case "k_win":
|
|
||||||
return (byte) 0xe3;
|
|
||||||
case "k_r_ctrl":
|
|
||||||
return (byte) 0xe4;
|
|
||||||
case "k_r_shift":
|
|
||||||
return (byte) 0xe5;
|
|
||||||
case "k_r_alt":
|
|
||||||
return (byte) 0xe6;
|
|
||||||
case "k_fn":
|
|
||||||
return (byte) 0xe7;
|
|
||||||
default:
|
|
||||||
return 0x00; // ???
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,8 @@ import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import logiled.About.AboutWindow;
|
import logiled.About.AboutWindow;
|
||||||
import logiled.MessagesConsumer;
|
import logiled.MessagesConsumer;
|
||||||
import logiled.USB.Communications;
|
import logiled.USB.EffectsThread;
|
||||||
|
import logiled.USB.KeyLedThread;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -34,6 +35,7 @@ public class MainController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private MenuItem aboutMenuItem;
|
private MenuItem aboutMenuItem;
|
||||||
|
|
||||||
|
// TODO: add block & release-button function
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle resourceBundle) {
|
public void initialize(URL url, ResourceBundle resourceBundle) {
|
||||||
|
@ -46,14 +48,16 @@ public class MainController implements Initializable {
|
||||||
HashMap<String, List<byte[][]>> rules = KeysLedsController.getRules();
|
HashMap<String, List<byte[][]>> rules = KeysLedsController.getRules();
|
||||||
if (rules == null)
|
if (rules == null)
|
||||||
return;
|
return;
|
||||||
Communications communications = new Communications(rules);
|
KeyLedThread keyLedThread = new KeyLedThread(rules);
|
||||||
Thread commThread = new Thread(communications);
|
Thread commThread = new Thread(keyLedThread);
|
||||||
commThread.setDaemon(true);
|
commThread.setDaemon(true);
|
||||||
commThread.start();
|
commThread.start();
|
||||||
}
|
}
|
||||||
else if (MainTabPane.getSelectionModel().getSelectedItem().getId().equals("EffectsTab")) {
|
else if (MainTabPane.getSelectionModel().getSelectedItem().getId().equals("EffectsTab")) {
|
||||||
// TODO
|
EffectsThread effectsThread = new EffectsThread(EffectsController.getEffect());
|
||||||
System.out.println(EffectsController.getEffect());
|
Thread commThread = new Thread(effectsThread);
|
||||||
|
commThread.setDaemon(true);
|
||||||
|
commThread.start();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class RuleBox extends HBox { // todo: add class to selected toggle user data; provide interface to add buttons to selected toggle
|
public class RuleBox extends HBox { // todo: add class to selected toggle user data; provide interface to add buttons to selected toggle
|
||||||
|
|
||||||
|
@ -37,6 +36,120 @@ public class RuleBox extends HBox { // todo: add class to selected toggle user
|
||||||
private final ColorPicker colorPicker;
|
private final ColorPicker colorPicker;
|
||||||
private final RadioButton radBtn;
|
private final RadioButton radBtn;
|
||||||
|
|
||||||
|
private static final Map<String, Byte> LoCodepage;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<String, Byte> stMap = new HashMap<>();
|
||||||
|
stMap.put("l_game", ((byte) 0x2));
|
||||||
|
stMap.put("l_caps",((byte) 0x3));
|
||||||
|
stMap.put("k_a",((byte) 0x4));
|
||||||
|
stMap.put("k_b",((byte) 0x5));
|
||||||
|
stMap.put("k_c",((byte) 0x6));
|
||||||
|
stMap.put("k_d",((byte) 0x7));
|
||||||
|
stMap.put("k_e",((byte) 0x8));
|
||||||
|
stMap.put("k_f",((byte) 0x9));
|
||||||
|
stMap.put("k_g",((byte) 0xA));
|
||||||
|
stMap.put("k_h",((byte) 0xB));
|
||||||
|
stMap.put("k_i",((byte) 0xC));
|
||||||
|
stMap.put("k_j",((byte) 0xD));
|
||||||
|
stMap.put("k_k",((byte) 0xE));
|
||||||
|
stMap.put("k_l",((byte) 0xF));
|
||||||
|
stMap.put("k_m",((byte) 0x10));
|
||||||
|
stMap.put("k_n",((byte) 0x11));
|
||||||
|
stMap.put("k_o",((byte) 0x12));
|
||||||
|
stMap.put("k_p",((byte) 0x13));
|
||||||
|
stMap.put("k_q",((byte) 0x14));
|
||||||
|
stMap.put("k_r",((byte) 0x15));
|
||||||
|
stMap.put("k_s",((byte) 0x16));
|
||||||
|
stMap.put("k_t",((byte) 0x17));
|
||||||
|
stMap.put("k_u",((byte) 0x18));
|
||||||
|
stMap.put("k_v",((byte) 0x19));
|
||||||
|
stMap.put("k_w",((byte) 0x1A));
|
||||||
|
stMap.put("k_x",((byte) 0x1B));
|
||||||
|
stMap.put("k_y",((byte) 0x1C));
|
||||||
|
stMap.put("k_z",((byte) 0x1D));
|
||||||
|
stMap.put("k_1",((byte) 0x1E));
|
||||||
|
stMap.put("k_2",((byte) 0x1F));
|
||||||
|
stMap.put("k_3",((byte) 0x20));
|
||||||
|
stMap.put("k_4",((byte) 0x21));
|
||||||
|
stMap.put("k_5",((byte) 0x22));
|
||||||
|
stMap.put("k_6",((byte) 0x23));
|
||||||
|
stMap.put("k_7",((byte) 0x24));
|
||||||
|
stMap.put("k_8",((byte) 0x25));
|
||||||
|
stMap.put("k_9",((byte) 0x26));
|
||||||
|
stMap.put("k_0",((byte) 0x27));
|
||||||
|
stMap.put("k_enter",((byte) 0x28));
|
||||||
|
stMap.put("k_esc",((byte) 0x29));
|
||||||
|
stMap.put("k_backspace",((byte) 0x2a));
|
||||||
|
stMap.put("k_tab",((byte) 0x2b));
|
||||||
|
stMap.put("k_space",((byte) 0x2c));
|
||||||
|
stMap.put("k_dash",((byte) 0x2d));
|
||||||
|
stMap.put("k_equal",((byte) 0x2e));
|
||||||
|
stMap.put("k_bracket_open",((byte) 0x2f));
|
||||||
|
stMap.put("k_bracket_close",((byte) 0x30));
|
||||||
|
stMap.put("k_backslash",((byte) 0x32));
|
||||||
|
stMap.put("k_semicolon",((byte) 0x33));
|
||||||
|
stMap.put("k_quotation",((byte) 0x34));
|
||||||
|
stMap.put("k_tilde",((byte) 0x35));
|
||||||
|
stMap.put("k_comma",((byte) 0x36));
|
||||||
|
stMap.put("k_dot",((byte) 0x37));
|
||||||
|
stMap.put("k_shash",((byte) 0x38));
|
||||||
|
stMap.put("k_caps",((byte) 0x39));
|
||||||
|
stMap.put("k_f1",((byte) 0x3a));
|
||||||
|
stMap.put("k_f2",((byte) 0x3b));
|
||||||
|
stMap.put("k_f3",((byte) 0x3c));
|
||||||
|
stMap.put("k_f4",((byte) 0x3d));
|
||||||
|
stMap.put("k_f5",((byte) 0x3e));
|
||||||
|
stMap.put("k_f6",((byte) 0x3f));
|
||||||
|
stMap.put("k_f7",((byte) 0x40));
|
||||||
|
stMap.put("k_f8",((byte) 0x41));
|
||||||
|
stMap.put("k_f9",((byte) 0x42));
|
||||||
|
stMap.put("k_f10",((byte) 0x43));
|
||||||
|
stMap.put("k_f11",((byte) 0x44));
|
||||||
|
stMap.put("k_f12",((byte) 0x45));
|
||||||
|
stMap.put("k_prtscr",((byte) 0x46));
|
||||||
|
stMap.put("k_scrl",((byte) 0x47));
|
||||||
|
stMap.put("k_pause",((byte) 0x48));
|
||||||
|
stMap.put("k_ins",((byte) 0x49));
|
||||||
|
stMap.put("k_home",((byte) 0x4a));
|
||||||
|
stMap.put("k_pg_up",((byte) 0x4b));
|
||||||
|
stMap.put("k_del",((byte) 0x4c));
|
||||||
|
stMap.put("k_end",((byte) 0x4d));
|
||||||
|
stMap.put("k_pg_dn",((byte) 0x4e));
|
||||||
|
stMap.put("k_arr_right",((byte) 0x4f));
|
||||||
|
stMap.put("k_arr_left",((byte) 0x50));
|
||||||
|
stMap.put("k_arr_down",((byte) 0x51));
|
||||||
|
stMap.put("k_arr_up",((byte) 0x52));
|
||||||
|
stMap.put("k_num",((byte) 0x53));
|
||||||
|
stMap.put("k_num_slash",((byte) 0x54));
|
||||||
|
stMap.put("k_num_asterisk",((byte) 0x55));
|
||||||
|
stMap.put("k_num_minus",((byte) 0x56));
|
||||||
|
stMap.put("k_num_plus",((byte) 0x57));
|
||||||
|
stMap.put("k_num_enter",((byte) 0x58));
|
||||||
|
stMap.put("k_num_1",((byte) 0x59));
|
||||||
|
stMap.put("k_num_2",((byte) 0x5a));
|
||||||
|
stMap.put("k_num_3",((byte) 0x5b));
|
||||||
|
stMap.put("k_num_4",((byte) 0x5c));
|
||||||
|
stMap.put("k_num_5",((byte) 0x5d));
|
||||||
|
stMap.put("k_num_6",((byte) 0x5e));
|
||||||
|
stMap.put("k_num_7",((byte) 0x5f));
|
||||||
|
stMap.put("k_num_8",((byte) 0x60));
|
||||||
|
stMap.put("k_num_9",((byte) 0x61));
|
||||||
|
stMap.put("k_num_0",((byte) 0x62));
|
||||||
|
stMap.put("k_num_period",((byte) 0x63));
|
||||||
|
stMap.put("k_menu",((byte) 0x65));
|
||||||
|
stMap.put("k_l_ctrl",((byte) 0xe0));
|
||||||
|
stMap.put("k_l_shift",((byte) 0xe1));
|
||||||
|
stMap.put("k_l_alt",((byte) 0xe2));
|
||||||
|
stMap.put("k_win",((byte) 0xe3));
|
||||||
|
stMap.put("k_r_ctrl",((byte) 0xe4));
|
||||||
|
stMap.put("k_r_shift",((byte) 0xe5));
|
||||||
|
stMap.put("k_r_alt",((byte) 0xe6));
|
||||||
|
stMap.put("k_fn",((byte) 0xe7));
|
||||||
|
|
||||||
|
LoCodepage = Collections.unmodifiableMap(stMap);
|
||||||
|
}
|
||||||
|
|
||||||
public RuleBox(){
|
public RuleBox(){
|
||||||
super();
|
super();
|
||||||
Insets insets = new Insets(3.0, 3.0, 3.0, 3.0);
|
Insets insets = new Insets(3.0, 3.0, 3.0, 3.0);
|
||||||
|
@ -122,7 +235,7 @@ public class RuleBox extends HBox { // todo: add class to selected toggle user
|
||||||
if (id.startsWith("l_"))
|
if (id.startsWith("l_"))
|
||||||
continue;
|
continue;
|
||||||
byte[] keyInfo = new byte[4]; // Where 0 - special key/indicator code; 1 - red; 2 - green; 3 - blue
|
byte[] keyInfo = new byte[4]; // Where 0 - special key/indicator code; 1 - red; 2 - green; 3 - blue
|
||||||
keyInfo[0] = LoCodepage.getCode(id);
|
keyInfo[0] = LoCodepage.get(id);
|
||||||
keyInfo[1] = red;
|
keyInfo[1] = red;
|
||||||
keyInfo[2] = green;
|
keyInfo[2] = green;
|
||||||
keyInfo[3] = blue;
|
keyInfo[3] = blue;
|
||||||
|
@ -150,7 +263,7 @@ public class RuleBox extends HBox { // todo: add class to selected toggle user
|
||||||
if (id.startsWith("k_"))
|
if (id.startsWith("k_"))
|
||||||
continue;
|
continue;
|
||||||
byte[] keyInfo = new byte[4]; // Where 0 - special key/indicator code; 1 - red; 2 - green; 3 - blue
|
byte[] keyInfo = new byte[4]; // Where 0 - special key/indicator code; 1 - red; 2 - green; 3 - blue
|
||||||
keyInfo[0] = LoCodepage.getCode(id);
|
keyInfo[0] = LoCodepage.get(id);
|
||||||
keyInfo[1] = red;
|
keyInfo[1] = red;
|
||||||
keyInfo[2] = green;
|
keyInfo[2] = green;
|
||||||
keyInfo[3] = blue;
|
keyInfo[3] = blue;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import java.util.Locale;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
public class MainFx extends Application {
|
public class MainFx extends Application {
|
||||||
public static final String appVersion = "v0.1";
|
public static final String appVersion = "v0.2";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception{
|
public void start(Stage primaryStage) throws Exception{
|
||||||
|
|
|
@ -24,9 +24,12 @@ public class RainbowHexDump {
|
||||||
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
|
System.out.println(">"+ANSI_RED+byteArray.length+ANSI_RESET);
|
||||||
for (byte b: byteArray)
|
for (byte b: byteArray)
|
||||||
System.out.print(String.format("%02x ", b));
|
System.out.print(String.format("%02x ", b));
|
||||||
|
System.out.println();
|
||||||
|
/*
|
||||||
System.out.print("\t\t\t"
|
System.out.print("\t\t\t"
|
||||||
+ new String(byteArray, StandardCharsets.UTF_8)
|
+ new String(byteArray, StandardCharsets.UTF_8)
|
||||||
+ "\n");
|
+ "\n");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void hexDumpUTF16LE(byte[] byteArray){
|
public static void hexDumpUTF16LE(byte[] byteArray){
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
package logiled.USB;
|
|
||||||
|
|
||||||
import logiled.MessagesConsumer;
|
|
||||||
import org.usb4java.DeviceHandle;
|
|
||||||
import org.usb4java.LibUsb;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.IntBuffer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Communications implements Runnable{
|
|
||||||
// Keys and indicators individual settings
|
|
||||||
private static final byte[] commit = {
|
|
||||||
0x11, (byte) 0xff, 0x0c, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final byte[] indicators = { // we have 2 leds on G513
|
|
||||||
// KEY RED GRN BLU -//-
|
|
||||||
0x12, (byte) 0xff, 0x0c, 0x3a, 0x00, 0x40, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] keys = { // Can store 14 rules
|
|
||||||
// LED RED GRN BLU -//-
|
|
||||||
0x12, (byte) 0xff, 0x0c, 0x3a, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
// -========= Effects =========-
|
|
||||||
private static final byte[] disable_colors = {
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] constant_color = {
|
|
||||||
// RED GRN BLU
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_horizontal = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_vertical = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_center_to_edge = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_horizontal_reverse = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_vertical_reverse = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] wave_edge_to_center = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x64, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] cycle = {
|
|
||||||
// !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] breathe = {
|
|
||||||
// RED GRN BLU !! !!
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
private static final byte[] cirles_on_press = {
|
|
||||||
// RED GRN BLU ms
|
|
||||||
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
// Game-key settings
|
|
||||||
//private static final byte[] game_key_rule
|
|
||||||
private static final byte[] game_key_set_default = {
|
|
||||||
0x11, (byte) 0xff, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
private DeviceHandle handler;
|
|
||||||
|
|
||||||
// What would be sent to keyboard
|
|
||||||
private List<byte[]> keyLedCommands;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to set keys & leds
|
|
||||||
* @param keyLedSet : set of rules, always not empty and not null
|
|
||||||
* */
|
|
||||||
public Communications(HashMap<String, List<byte[][]>> keyLedSet){
|
|
||||||
keyLedCommands = new ArrayList<>();
|
|
||||||
|
|
||||||
int appendTo = 8;
|
|
||||||
|
|
||||||
byte[] command = Arrays.copyOfRange(indicators, 0, indicators.length);
|
|
||||||
|
|
||||||
for (byte[][] singleRuleSet : keyLedSet.get("Led")){
|
|
||||||
for (byte[] keyLedSetting: singleRuleSet) {
|
|
||||||
System.arraycopy(keyLedSetting, 0, command, appendTo, 4);
|
|
||||||
appendTo += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appendTo > 8) {
|
|
||||||
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
|
||||||
appendTo = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
command = Arrays.copyOfRange(keys, 0, keys.length);
|
|
||||||
|
|
||||||
for (byte[][] singleRuleSet : keyLedSet.get("Key")) {
|
|
||||||
for (byte[] keyLedSetting : singleRuleSet){
|
|
||||||
if (appendTo == 64){
|
|
||||||
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
|
||||||
command = Arrays.copyOfRange(keys, 0, keys.length);
|
|
||||||
appendTo = 8;
|
|
||||||
}
|
|
||||||
System.arraycopy(keyLedSetting, 0, command, appendTo, 4);
|
|
||||||
appendTo += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appendTo > 8)
|
|
||||||
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
|
||||||
// Add commit command to the end
|
|
||||||
keyLedCommands.add(commit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// If no commands in the query, then nothing to do
|
|
||||||
if (keyLedCommands.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UsbConnect usbConnect = new UsbConnect();
|
|
||||||
|
|
||||||
if (!usbConnect.isConnected())
|
|
||||||
return;
|
|
||||||
|
|
||||||
handler = usbConnect.getHandlerKbrd();
|
|
||||||
|
|
||||||
for (byte[] cmd : keyLedCommands)
|
|
||||||
if (write(cmd))
|
|
||||||
break;
|
|
||||||
|
|
||||||
usbConnect.close();
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Write to keyboard
|
|
||||||
* @param message : what to sent
|
|
||||||
* @return true in case of failure
|
|
||||||
* false for success
|
|
||||||
* */
|
|
||||||
private boolean write(byte[] message){
|
|
||||||
ByteBuffer writeBuffer = ByteBuffer.allocateDirect(message.length); //writeBuffer.order() equals BIG_ENDIAN;
|
|
||||||
writeBuffer.put(message); // Don't do writeBuffer.rewind();
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if (message.length > 20)
|
|
||||||
result = LibUsb.controlTransfer(handler, (byte) 0x21, (byte) 0x09, (short) 0x212, (short) 1, writeBuffer, 2000);
|
|
||||||
else
|
|
||||||
result = LibUsb.controlTransfer(handler, (byte) 0x21, (byte) 0x09, (short) 0x211, (short) 1, writeBuffer, 2000);
|
|
||||||
|
|
||||||
if (result < 0){
|
|
||||||
MessagesConsumer.getInstance().inform("Data transfer failed: "+UsbErrorCodes.getErrCode(result));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer readBuffer = ByteBuffer.allocateDirect(64);
|
|
||||||
IntBuffer readBufTrans = IntBuffer.allocate(1);
|
|
||||||
LibUsb.interruptTransfer(handler, (byte) 0x82, readBuffer, readBufTrans, 1000);
|
|
||||||
/*
|
|
||||||
readBuffer.rewind();
|
|
||||||
byte[] arr = new byte[readBuffer.get()];
|
|
||||||
readBuffer.get(arr);
|
|
||||||
RainbowHexDump.hexDumpUTF8(arr);
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
ANY
|
|
||||||
0x11, 0xff, ???, 0x3c
|
|
||||||
|
|
||||||
waves
|
|
||||||
cwave
|
|
||||||
!! !!
|
|
||||||
0x11, 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x56, 0x00 0x00, ----, ----, ----, ----, ====, 0x64, ????, ?!!?, 0x00, 0x00, 0x00
|
|
||||||
|
|
||||||
hwave
|
|
||||||
vwave
|
|
||||||
!! !!
|
|
||||||
0x11, 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x55, 0x00 0x00, ----, ----, ----, ----, ====, 0x64, ????, ?!!?, 0x00, 0x00, 0x00
|
|
||||||
|
|
||||||
cycle
|
|
||||||
!! !!
|
|
||||||
0x11, 0xff, 0x0d, 0x3c, 0x00, 0x03, 0x55, 0x00 0x00, ----, ----, ----, ----, 0x00, 0x64, ????, ?!!?, 0x00, 0x00, 0x00
|
|
||||||
|
|
||||||
breathing
|
|
||||||
|
|
||||||
0x11, 0xff, 0x0d, 0x3c, 0x00, 0x02, RED_, GRN_, BLU_ ----, ----, ----, ----, 0x00, 0x64, ????, ?!!?, 0x00, 0x00, 0x00
|
|
||||||
|
|
||||||
----------------------
|
|
||||||
hwave - new
|
|
||||||
11 ff 0d 3c 00 04 00 00 00 00 00 00 e8 06 64 03 00 00 00 00
|
|
||||||
|
|
||||||
|
|
||||||
* */
|
|
145
src/main/java/logiled/USB/EffectsThread.java
Normal file
145
src/main/java/logiled/USB/EffectsThread.java
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
package logiled.USB;
|
||||||
|
|
||||||
|
import logiled.Controllers.LoEffects;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class EffectsThread extends LoThread implements Runnable{
|
||||||
|
|
||||||
|
private byte[] command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set effects
|
||||||
|
* @param effectData : set of rules, always not empty and not null
|
||||||
|
* */
|
||||||
|
public EffectsThread(HashMap<String, Byte> effectData){
|
||||||
|
switch (LoEffects.values()[effectData.get("EFFECT")]){
|
||||||
|
case DISABLE:
|
||||||
|
command = effectDisable();
|
||||||
|
break;
|
||||||
|
case CONSTANT_COLOR:
|
||||||
|
command = effectConstantColor(effectData);
|
||||||
|
break;
|
||||||
|
case BREATH:
|
||||||
|
command = effectBreath(effectData);
|
||||||
|
break;
|
||||||
|
case CIRCLES_ON_PRESS:
|
||||||
|
command = effectCirlesOnPress(effectData);
|
||||||
|
break;
|
||||||
|
case CYCLE:
|
||||||
|
command = effectCycle(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_HORIZONTAL_FRW:
|
||||||
|
command = effectWaveHorizontalFrw(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_VERTICAL_FRW:
|
||||||
|
command = effectWaveVerticalFrw(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_CENTER_TO_EDGE:
|
||||||
|
command = effectWaveCenterToEdge(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_HORIZONTAL_BKW:
|
||||||
|
command = effectWaveHorizontalBkw(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_VERTICAL_BKW:
|
||||||
|
command = effectWaveVerticalBkw(effectData);
|
||||||
|
break;
|
||||||
|
case WAVE_EDGE_TO_CENTER:
|
||||||
|
command = effectWaveEdgeToCenter(effectData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (command == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UsbConnect usbConnect = new UsbConnect();
|
||||||
|
|
||||||
|
if (!usbConnect.isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
handler = usbConnect.getHandlerKbrd();
|
||||||
|
|
||||||
|
write(command);
|
||||||
|
|
||||||
|
usbConnect.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectDisable(){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectConstantColor(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x01, effectData.get("RED"), effectData.get("GREEN"), effectData.get("BLUE"), 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectBreath(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x02, effectData.get("RED"), effectData.get("GREEN"), effectData.get("BLUE"), effectData.get("TIME_HIGH"), effectData.get("TIME_LOW"), 0x00, 0x64, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectCirlesOnPress(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x06, effectData.get("RED"), effectData.get("GREEN"), effectData.get("BLUE"), 0x00, 0x00, effectData.get("TIME_LOW"), 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectCycle(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_HIGH"), effectData.get("TIME_LOW"), 0x64, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveHorizontalFrw(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x01, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveVerticalFrw(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x02, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveCenterToEdge(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x03, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveHorizontalBkw(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x06, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveVerticalBkw(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x07, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] effectWaveEdgeToCenter(HashMap<String, Byte> effectData){
|
||||||
|
return new byte[] {
|
||||||
|
0x11, (byte) 0xff, 0x0d, 0x3c, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, effectData.get("TIME_LOW"), 0x08, 0x64, effectData.get("TIME_HIGH"),
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/logiled/USB/GameModeThread.java
Normal file
41
src/main/java/logiled/USB/GameModeThread.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package logiled.USB;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GameModeThread extends LoThread implements Runnable{
|
||||||
|
|
||||||
|
// Game-key settings
|
||||||
|
//private static final byte[] game_key_rule
|
||||||
|
private static final byte[] game_key_set_default = {
|
||||||
|
0x11, (byte) 0xff, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
private byte[] command;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set keys & leds
|
||||||
|
* @param keysToDisable : list of keys that has to be disables in 'Game Mode', always not empty and not null
|
||||||
|
* */
|
||||||
|
public GameModeThread(List<Byte> keysToDisable){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (command == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UsbConnect usbConnect = new UsbConnect();
|
||||||
|
|
||||||
|
if (!usbConnect.isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
handler = usbConnect.getHandlerKbrd();
|
||||||
|
|
||||||
|
write(command);
|
||||||
|
|
||||||
|
usbConnect.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
97
src/main/java/logiled/USB/KeyLedThread.java
Normal file
97
src/main/java/logiled/USB/KeyLedThread.java
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
package logiled.USB;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KeyLedThread extends LoThread implements Runnable{
|
||||||
|
// Keys and indicators individual settings
|
||||||
|
private static final byte[] commit = {
|
||||||
|
0x11, (byte) 0xff, 0x0c, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] indicators = { // we have 2 leds on G513
|
||||||
|
// KEY RED GRN BLU -//-
|
||||||
|
0x12, (byte) 0xff, 0x0c, 0x3a, 0x00, 0x40, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
private static final byte[] keys = { // Can store 14 rules
|
||||||
|
// LED RED GRN BLU -//-
|
||||||
|
0x12, (byte) 0xff, 0x0c, 0x3a, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// What would be sent to keyboard
|
||||||
|
private List<byte[]> keyLedCommands;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set keys & leds
|
||||||
|
* @param keyLedSet : set of rules, always not empty and not null
|
||||||
|
* */
|
||||||
|
public KeyLedThread(HashMap<String, List<byte[][]>> keyLedSet){
|
||||||
|
keyLedCommands = new ArrayList<>();
|
||||||
|
|
||||||
|
int appendTo = 8;
|
||||||
|
|
||||||
|
byte[] command = Arrays.copyOfRange(indicators, 0, indicators.length);
|
||||||
|
|
||||||
|
for (byte[][] singleRuleSet : keyLedSet.get("Led")){
|
||||||
|
for (byte[] keyLedSetting: singleRuleSet) {
|
||||||
|
System.arraycopy(keyLedSetting, 0, command, appendTo, 4);
|
||||||
|
appendTo += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appendTo > 8) {
|
||||||
|
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
||||||
|
appendTo = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
command = Arrays.copyOfRange(keys, 0, keys.length);
|
||||||
|
|
||||||
|
for (byte[][] singleRuleSet : keyLedSet.get("Key")) {
|
||||||
|
for (byte[] keyLedSetting : singleRuleSet){
|
||||||
|
if (appendTo == 64){
|
||||||
|
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
||||||
|
command = Arrays.copyOfRange(keys, 0, keys.length);
|
||||||
|
appendTo = 8;
|
||||||
|
}
|
||||||
|
System.arraycopy(keyLedSetting, 0, command, appendTo, 4);
|
||||||
|
appendTo += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appendTo > 8)
|
||||||
|
keyLedCommands.add(Arrays.copyOfRange(command, 0, command.length));
|
||||||
|
// Add commit command to the end
|
||||||
|
keyLedCommands.add(commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// If no commands in the query, then nothing to do
|
||||||
|
if (keyLedCommands.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UsbConnect usbConnect = new UsbConnect();
|
||||||
|
|
||||||
|
if (!usbConnect.isConnected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
handler = usbConnect.getHandlerKbrd();
|
||||||
|
|
||||||
|
for (byte[] cmd : keyLedCommands)
|
||||||
|
if (write(cmd))
|
||||||
|
break;
|
||||||
|
|
||||||
|
usbConnect.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
src/main/java/logiled/USB/LoThread.java
Normal file
46
src/main/java/logiled/USB/LoThread.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package logiled.USB;
|
||||||
|
|
||||||
|
import logiled.MessagesConsumer;
|
||||||
|
import org.usb4java.DeviceHandle;
|
||||||
|
import org.usb4java.LibUsb;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.IntBuffer;
|
||||||
|
|
||||||
|
abstract class LoThread {
|
||||||
|
|
||||||
|
DeviceHandle handler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write to keyboard
|
||||||
|
* @param message : what to sent
|
||||||
|
* @return true in case of failure
|
||||||
|
* false for success
|
||||||
|
* */
|
||||||
|
boolean write(byte[] message){
|
||||||
|
ByteBuffer writeBuffer = ByteBuffer.allocateDirect(message.length); //writeBuffer.order() equals BIG_ENDIAN;
|
||||||
|
writeBuffer.put(message); // Don't do writeBuffer.rewind();
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (message.length > 20)
|
||||||
|
result = LibUsb.controlTransfer(handler, (byte) 0x21, (byte) 0x09, (short) 0x212, (short) 1, writeBuffer, 2000);
|
||||||
|
else
|
||||||
|
result = LibUsb.controlTransfer(handler, (byte) 0x21, (byte) 0x09, (short) 0x211, (short) 1, writeBuffer, 2000);
|
||||||
|
|
||||||
|
if (result < 0){
|
||||||
|
MessagesConsumer.getInstance().inform("Data transfer failed: "+UsbErrorCodes.getErrCode(result));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer readBuffer = ByteBuffer.allocateDirect(64);
|
||||||
|
IntBuffer readBufTrans = IntBuffer.allocate(1);
|
||||||
|
LibUsb.interruptTransfer(handler, (byte) 0x82, readBuffer, readBufTrans, 1000);
|
||||||
|
/*
|
||||||
|
readBuffer.rewind();
|
||||||
|
byte[] arr = new byte[readBuffer.get()];
|
||||||
|
readBuffer.get(arr);
|
||||||
|
RainbowHexDump.hexDumpUTF8(arr);
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,14 +15,17 @@
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
<Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
|
||||||
</padding>
|
</padding>
|
||||||
|
<children>
|
||||||
|
<HBox spacing="5.0">
|
||||||
<children>
|
<children>
|
||||||
<MenuButton fx:id="effectsMenu" mnemonicParsing="false">
|
<MenuButton fx:id="effectsMenu" mnemonicParsing="false">
|
||||||
<items>
|
<items>
|
||||||
<RadioMenuItem fx:id="disRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_disable">
|
<RadioMenuItem fx:id="disRMI" mnemonicParsing="false" onAction="#selectEffect" selected="true" text="%effect_disable">
|
||||||
<toggleGroup>
|
<toggleGroup>
|
||||||
<ToggleGroup fx:id="effectsToggleGrp" />
|
<ToggleGroup fx:id="effectsToggleGrp" />
|
||||||
</toggleGroup></RadioMenuItem>
|
</toggleGroup>
|
||||||
<RadioMenuItem fx:id="constRMI" mnemonicParsing="false" onAction="#selectEffect" selected="true" text="%effect_constant" toggleGroup="$effectsToggleGrp" />
|
</RadioMenuItem>
|
||||||
|
<RadioMenuItem fx:id="constRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_constant" toggleGroup="$effectsToggleGrp" />
|
||||||
<RadioMenuItem fx:id="breathRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_breath" toggleGroup="$effectsToggleGrp" />
|
<RadioMenuItem fx:id="breathRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_breath" toggleGroup="$effectsToggleGrp" />
|
||||||
<RadioMenuItem fx:id="circlesOnPressRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_cirles_on_press" toggleGroup="$effectsToggleGrp" />
|
<RadioMenuItem fx:id="circlesOnPressRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_cirles_on_press" toggleGroup="$effectsToggleGrp" />
|
||||||
<RadioMenuItem fx:id="cycleRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_cycle" toggleGroup="$effectsToggleGrp" />
|
<RadioMenuItem fx:id="cycleRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_cycle" toggleGroup="$effectsToggleGrp" />
|
||||||
|
@ -34,6 +37,9 @@
|
||||||
<RadioMenuItem fx:id="edgToCntrWaveRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_wave_edge_to_center" toggleGroup="$effectsToggleGrp" />
|
<RadioMenuItem fx:id="edgToCntrWaveRMI" mnemonicParsing="false" onAction="#selectEffect" text="%effect_wave_edge_to_center" toggleGroup="$effectsToggleGrp" />
|
||||||
</items>
|
</items>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
|
<ColorPicker fx:id="mainClrPkr" visible="false" />
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
<Separator prefWidth="200.0" />
|
<Separator prefWidth="200.0" />
|
||||||
<HBox alignment="CENTER_LEFT" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="35.0">
|
<HBox alignment="CENTER_LEFT" maxHeight="-Infinity" minHeight="-Infinity" prefHeight="35.0">
|
||||||
<children>
|
<children>
|
||||||
|
@ -45,6 +51,5 @@
|
||||||
<Label fx:id="mainSlideInfoLbl" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="40.0" textFill="DIMGRAY" visible="false" />
|
<Label fx:id="mainSlideInfoLbl" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="40.0" textFill="DIMGRAY" visible="false" />
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<ColorPicker fx:id="mainClrPkr" visible="false" />
|
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
|
|
@ -13,8 +13,8 @@ effect_constant=Постоянный цвет
|
||||||
effect_breath=Дыхание
|
effect_breath=Дыхание
|
||||||
effect_cirles_on_press=Круги при нажатии
|
effect_cirles_on_press=Круги при нажатии
|
||||||
effect_cycle=Цикл
|
effect_cycle=Цикл
|
||||||
effect_wave_horizontal=Волна по-горизонтали
|
effect_wave_horizontal=Волна горизонтальная
|
||||||
effect_wave_horizontal_reverse=Волна по-горизонтали (обратная)
|
effect_wave_horizontal_reverse=Волна горизонтальная (обратная)
|
||||||
effect_wave_vertical=Волна вертикальная
|
effect_wave_vertical=Волна вертикальная
|
||||||
effect_wave_vertical_reverse=Волна вертикальная (обратная)
|
effect_wave_vertical_reverse=Волна вертикальная (обратная)
|
||||||
effect_wave_center_to_edge=Волна от центра к краям
|
effect_wave_center_to_edge=Волна от центра к краям
|
||||||
|
|
Loading…
Reference in a new issue