ui improvements and texture tests
This commit is contained in:
@@ -8,6 +8,7 @@ LDLIBS := -lraylib -lasound -llibremidi -pthread
|
||||
LDFLAGS := -Llib -L/usr/lib -L/usr/local/lib
|
||||
|
||||
SRCS := $(wildcard src/*.cpp)
|
||||
HDRS := $(wildcard src/*.h)
|
||||
OBJECTS := $(patsubst src/%.cpp,build/%.o, $(SRCS))
|
||||
|
||||
viseq: $(OBJECTS)
|
||||
@@ -17,6 +18,9 @@ $(OBJECTS): build/%.o : src/%.cpp
|
||||
@mkdir -p build
|
||||
$(CXX) -c $< -o $@ $(CXXFLAGS) $(CXXINC)
|
||||
|
||||
src/%.cpp: $HDRS
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
rm -f build/*
|
||||
rm -f viseq
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -12,6 +12,13 @@ inline bool ViButton(Vec2Df mp, float x, float y, float radius, Color color){
|
||||
return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
|
||||
}
|
||||
|
||||
inline bool ViTexButton(Vec2Df mp, Vec2Df position, float rotation, float radius, Texture2D tex, Color color){
|
||||
float scale = (radius*2.0f) / (float)tex.width;
|
||||
Vec2Df center_pos = position - Vec2Df((tex.width*scale)/1.0f * sin(rotation), (tex.height*scale)/1.0f * cos(rotation));
|
||||
DrawTextureEx(tex, center_pos, rotation, scale, color);
|
||||
return (Vector2Distance(mp, position) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
|
||||
}
|
||||
|
||||
inline bool ViButton(Vec2Df mp, Vec2Df position, float radius, Color color){
|
||||
return ViButton(mp, position.x, position.y, radius, color);
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,14 +21,14 @@ namespace VISEQ::APP::CANVAS {
|
||||
}
|
||||
|
||||
void Canvas::pickUp() {
|
||||
std::cout << "canvas pickUp" << std::endl;
|
||||
//std::cout << "canvas pickUp" << std::endl;
|
||||
BASE::Draggable::pickUp();
|
||||
select_start = SCREEN_MOUSE;
|
||||
state->pushEvent({getPtr(), Interaction::DESELECT});
|
||||
}
|
||||
|
||||
void Canvas::putDown() {
|
||||
std::cout << "canvas putDown" << std::endl;
|
||||
//std::cout << "canvas putDown" << std::endl;
|
||||
BASE::Draggable::putDown();
|
||||
state->pushEvent({getPtr(), Interaction::SELECT});
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define VS_COLOR_PURPLE (Color){158, 134, 200, 255}
|
||||
#define VS_COLOR_PINK (Color){176, 82, 121, 255}
|
||||
#define VS_COLOR_BLUE (Color){108, 153, 187, 255}
|
||||
#define VS_COLOR_LIGHTBLUE (Color){143, 206, 255, 255}
|
||||
|
||||
#define VS_COLOR_RED (Color){195, 83, 85, 255}
|
||||
#define VS_COLOR_BROWN (Color){84, 75, 61, 255}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "config-node.h"
|
||||
#include "datatypes.h"
|
||||
#include "helper.h"
|
||||
#include "state.h"
|
||||
#include "vmath.h"
|
||||
#include "raylib.h"
|
||||
@@ -29,6 +30,10 @@ namespace VISEQ::GRAPH{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
void GraphManager::loadTextures(){
|
||||
tex_delete = LoadTexture("resources/textures/round-delete.png");
|
||||
}
|
||||
|
||||
int GraphManager::getNodesSize(){
|
||||
return nodes.size();
|
||||
}
|
||||
@@ -344,6 +349,7 @@ namespace VISEQ::GRAPH{
|
||||
void GraphManager::update(){
|
||||
if(!remove_edges.empty()) removeEdges();
|
||||
if(!split_edges.empty()) splitEdges();
|
||||
if(tex_delete.width == 0 && IsWindowReady()) loadTextures();
|
||||
}
|
||||
|
||||
void GraphManager::drawEdges(Vec2Df mouse_pos, Camera2D cam){
|
||||
@@ -365,6 +371,8 @@ namespace VISEQ::GRAPH{
|
||||
unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f);
|
||||
unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f);
|
||||
|
||||
float opacity_normalized = Clamp((float)opacity / 255.0f, .0f, 1.0f);
|
||||
|
||||
float midi_gate_v1 = 0.0f;
|
||||
float midi_gate_v2 = 0.0f;
|
||||
|
||||
@@ -426,7 +434,7 @@ namespace VISEQ::GRAPH{
|
||||
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, VS_COLOR_BLUE);
|
||||
}
|
||||
|
||||
if(ViButton(mouse_pos, flip_handle.x, flip_handle.y, 8.0f, (Color){232, 50, 32, opacity} )) removeEdge(c);
|
||||
if(IsWindowReady() && ViTexButton(mouse_pos, flip_handle, HELPER::GetRotation(from_to_handle, to_from_handle), 8.0f, tex_delete, ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), opacity_normalized) )) removeEdge(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace VISEQ::GRAPH {
|
||||
GraphManager() {}
|
||||
|
||||
std::shared_ptr<GraphManager> getPtr();
|
||||
void loadTextures();
|
||||
int getNodesSize();
|
||||
void createMidiNode(Vec2Df position);
|
||||
void createConfigNode(Vec2Df position);
|
||||
@@ -84,6 +85,8 @@ namespace VISEQ::GRAPH {
|
||||
|
||||
friend void from_json(const json& j, std::shared_ptr<GraphManager>& G);
|
||||
friend void to_json(json& j, const std::shared_ptr<GraphManager>& G);
|
||||
|
||||
Texture2D tex_delete;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -15,4 +15,8 @@ namespace VISEQ::HELPER{
|
||||
float rotation = Vector2Angle((Vector2){1,0}, (end - start)) * RAD2DEG;
|
||||
DrawTextPro(GetFontDefault(), text.c_str(), text_position, (Vector2){0,0}, rotation, size, 2.0f, col);
|
||||
}
|
||||
|
||||
inline float GetRotation(Vec2Df start, Vec2Df end){
|
||||
return Vector2Angle((Vector2){1,0}, (end - start)) * RAD2DEG;
|
||||
}
|
||||
}
|
||||
|
||||
+46
-28
@@ -198,21 +198,24 @@ namespace VISEQ::GRAPH::NODES {
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPCProgram(wheel);
|
||||
break;}
|
||||
case PB:{
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*100);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*1000);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*10);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*64);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*2048);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*256);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel);
|
||||
break;}
|
||||
case AT:{
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*100);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*1000);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*10);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*10);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*100);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel);
|
||||
break;}
|
||||
case PP:{
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPolyPressureNote(wheel);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPolyPressureNote(wheel*10);
|
||||
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*100);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*1000);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*10);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*64);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*2048);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*256);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel);
|
||||
break;}
|
||||
};
|
||||
}
|
||||
@@ -252,23 +255,22 @@ namespace VISEQ::GRAPH::NODES {
|
||||
break;}
|
||||
}
|
||||
|
||||
DrawRing(position, radius, radius + 4, 0, 360, 24, (Color){60, 60, 60, 255});
|
||||
DrawRing(position, radius, radius + 4, 0.0f - 90.0f, (360.0f/127.0f) * getNotes().velocity - 90.0f, 24, (Color){158, 134, 200, 255});
|
||||
DrawCircleLinesV(position, radius + 4, (Color){100, 100, 100, 255});
|
||||
DrawRing(position, radius, radius + 4, 0, 360, 24, VS_COLOR_DARKGREY);
|
||||
//DrawRing(position, radius, radius + 4, 0.0f - 90.0f, (360.0f/127.0f) * getNotes().velocity - 90.0f, 24, (Color){158, 134, 200, 255});
|
||||
if(!selected) DrawCircleLinesV(position, radius + 4, VS_COLOR_GREY);
|
||||
|
||||
float trigger_alpha = (1.f / getNotes().gate) * fade;
|
||||
|
||||
if(!picked_up && !selected && !in_selection_rect && !hovering()) DrawCircle(position.x, position.y, radius, ColorLerp(state->mode_color, VS_COLOR_RED, trigger_alpha));
|
||||
if(picked_up || in_selection_rect || hovering()) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255});
|
||||
if(selected) DrawCircle(position.x, position.y, radius, (Color){255, 153, 187, 255});
|
||||
DrawCircle(position.x, position.y, radius, ColorLerp(state->settings.mode_colors[mode], VS_COLOR_RED, trigger_alpha));
|
||||
if(hovering()) DrawCircleLinesV(position, radius + 4, VS_COLOR_PINK);
|
||||
if(picked_up || (in_selection_rect && MOUSE_LEFT.down) || selected) DrawCircleLinesV(position, radius + 4, VS_COLOR_LIGHTBLUE);
|
||||
//if(selected) DrawCircle(position.x, position.y, radius, (Color){255, 153, 187, 255});
|
||||
|
||||
if(distributionMode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK);
|
||||
if(distributionMode == Distribution::ROUNDROBIN) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_YELLOW);
|
||||
|
||||
if(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255});
|
||||
//if(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255});
|
||||
|
||||
// TODO draw values of corresponding attribute when modifiers are pressed
|
||||
//VMATH::Vec2D<float> title_position = position + VMATH::Vec2D<float>(radius + 7.0f, -(radius + 7.0f));
|
||||
VMATH::Vec2D<float> desc_position = position + VMATH::Vec2D<float>(radius + 7.0f, radius + 7.0f);
|
||||
switch(mode){
|
||||
case NOTE:{
|
||||
@@ -285,10 +287,10 @@ namespace VISEQ::GRAPH::NODES {
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("VALUE", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("VELOCITY", desc_position, 8, WHITE);
|
||||
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE +.1", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE +1.0", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE +.01", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE +.001", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE 0.1s", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE 1.0s", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE 0.01s", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("GATE 0.001s", desc_position, 8, WHITE);
|
||||
}
|
||||
break;}
|
||||
case CC:{
|
||||
@@ -310,14 +312,23 @@ namespace VISEQ::GRAPH::NODES {
|
||||
}
|
||||
break;}
|
||||
case PB:{
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPitchBend().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPitchBend().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPitchBend().value), position, 12, WHITE);
|
||||
DrawCenteredText(std::format("{}", getPitchBend().value), position, 10, WHITE);
|
||||
if(selected){
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("PITCHBEND", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("64", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("2048", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("256", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, WHITE);
|
||||
}
|
||||
break;}
|
||||
case AT:{
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, WHITE);
|
||||
DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, WHITE);
|
||||
if(selected){
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("AFTERTOUCH", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("10", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("100", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, WHITE);
|
||||
}
|
||||
break;}
|
||||
case PP:{
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawCenteredText(MIDI::Notes[getPolyPressure().note], position, 12, WHITE);
|
||||
@@ -325,6 +336,13 @@ namespace VISEQ::GRAPH::NODES {
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, WHITE);
|
||||
if(selected){
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("POLYPRESSURE", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("64", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("2048", desc_position, 8, WHITE);
|
||||
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("256", desc_position, 8, WHITE);
|
||||
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, WHITE);
|
||||
}
|
||||
break;}
|
||||
};
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ namespace VISEQ::GRAPH::NODES {
|
||||
c->update();
|
||||
}
|
||||
if(free_connectors == 0) addConnector();
|
||||
in_selection_rect = CheckCollisionPointRec(position, state->selection);
|
||||
}
|
||||
|
||||
void Node::draw(Vec2Df mp, Camera2D cam) {}
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace VISEQ::BASE {
|
||||
bool erase = false;
|
||||
Vec2Df selection_offset;
|
||||
|
||||
void update();
|
||||
virtual bool clicked() override;
|
||||
|
||||
virtual bool select() = 0;
|
||||
|
||||
+8
-8
@@ -93,14 +93,14 @@ namespace VISEQ::APP::UI{
|
||||
DrawText(std::format("{}", gm->getNodesSize()).c_str(), 20, state->settings.height - 70, 15, VS_COLOR_WHITE);
|
||||
DrawFPS(20, state->settings.height - 30);
|
||||
|
||||
std::string shorts[6] = {"NT","CC","PC","PB","AT","PP"};
|
||||
for(int i = 0; i < 6; ++i){
|
||||
Color col = state->settings.mode_colors[i];
|
||||
Vec2Df pos = {state->settings.width - (6.0f*75.0f) + i*75.0f, state->settings.height - 75.0f};
|
||||
DrawRing(pos, 30.0f, 34.0f, 0.0f, 360.0f, 24, state->node_mode == i ? VS_COLOR_WHITE : (Color){0,0,0,0});
|
||||
DrawCircleV(pos, 30.0f, col);
|
||||
DrawCenteredText(shorts[i], pos, 20, WHITE);
|
||||
}
|
||||
// std::string shorts[6] = {"NT","CC","PC","PB","AT","PP"};
|
||||
// for(int i = 0; i < 6; ++i){
|
||||
// Color col = state->settings.mode_colors[i];
|
||||
// Vec2Df pos = {state->settings.width - (6.0f*75.0f) + i*75.0f, state->settings.height - 75.0f};
|
||||
// DrawRing(pos, 30.0f, 34.0f, 0.0f, 360.0f, 24, state->node_mode == i ? VS_COLOR_WHITE : (Color){0,0,0,0});
|
||||
// DrawCircleV(pos, 30.0f, col);
|
||||
// DrawCenteredText(shorts[i], pos, 20, WHITE);
|
||||
// }
|
||||
}
|
||||
|
||||
void AppUI::DrawCenteredText(std::string text, Vec2Df position, int size, Color color){
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ namespace VISEQ::VMATH{
|
||||
|
||||
template<typename T>
|
||||
Vec2D<T> polarToCartesian(T r, T q) {
|
||||
return Vec2D<T>{r * cos(q), r * sin(q)};
|
||||
return Vec2D<T>{r * (T)cos(q), r * (T)sin(q)};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user