mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2024-11-22 10:35:16 +01:00
Merge branch 'mc/1.13'
This commit is contained in:
commit
d34628dfdf
@ -40,8 +40,6 @@
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@ -122,8 +120,7 @@ public void renderMaps() throws IOException {
|
||||
config.getWebDataPath().resolve(mapConfig.getId()).resolve("hires"),
|
||||
resourcePack,
|
||||
mapConfig,
|
||||
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
|
||||
ForkJoinPool.commonPool()
|
||||
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize())
|
||||
);
|
||||
|
||||
LowresModelManager lowresModelManager = new LowresModelManager(
|
||||
@ -224,6 +221,8 @@ public void renderMaps() throws IOException {
|
||||
|
||||
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
||||
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||
if (currentTask == null) continue;
|
||||
|
||||
lastLogUpdate = now;
|
||||
long time = currentTask.getActiveTime();
|
||||
|
||||
@ -243,6 +242,7 @@ public void renderMaps() throws IOException {
|
||||
|
||||
if (lastSave < now - 1 * 60000) { // save every minute
|
||||
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||
if (currentTask == null) continue;
|
||||
|
||||
lastSave = now;
|
||||
currentTask.getMapType().getTileRenderer().save();
|
||||
@ -272,11 +272,6 @@ public void renderMaps() throws IOException {
|
||||
} catch (IOException e) {
|
||||
Logger.global.logError("Failed to update web-settings!", e);
|
||||
}
|
||||
|
||||
Logger.global.logInfo("Waiting for all threads to quit ...");
|
||||
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
||||
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
||||
}
|
||||
|
||||
Logger.global.logInfo("Render finished!");
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ public synchronized void start() {
|
||||
|
||||
for (int i = 0; i < renderThreads.length; i++) {
|
||||
renderThreads[i] = new Thread(this::renderThread);
|
||||
renderThreads[i].setDaemon(true);
|
||||
renderThreads[i].setPriority(Thread.MIN_PRIORITY);
|
||||
renderThreads[i].start();
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
@ -184,8 +183,7 @@ public synchronized void load() throws IOException, ParseResourceException {
|
||||
config.getWebDataPath().resolve(id).resolve("hires"),
|
||||
resourcePack,
|
||||
mapConfig,
|
||||
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize()),
|
||||
ForkJoinPool.commonPool()
|
||||
new Vector2i(mapConfig.getHiresTileSize(), mapConfig.getHiresTileSize())
|
||||
);
|
||||
|
||||
LowresModelManager lowresModelManager = new LowresModelManager(
|
||||
|
@ -35,7 +35,6 @@
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import com.flowpowered.math.vector.Vector2i;
|
||||
@ -57,22 +56,19 @@ public class HiresModelManager {
|
||||
private Vector2i tileSize;
|
||||
private Vector2i gridOrigin;
|
||||
|
||||
private ExecutorService savingExecutor;
|
||||
|
||||
private boolean useGzip;
|
||||
|
||||
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, RenderSettings renderSettings, Vector2i tileSize, ExecutorService savingExecutor) {
|
||||
this(fileRoot, new HiresModelRenderer(resourcePack, renderSettings), tileSize, new Vector2i(2, 2), savingExecutor, renderSettings.useGzipCompression());
|
||||
public HiresModelManager(Path fileRoot, ResourcePack resourcePack, RenderSettings renderSettings, Vector2i tileSize) {
|
||||
this(fileRoot, new HiresModelRenderer(resourcePack, renderSettings), tileSize, new Vector2i(2, 2), renderSettings.useGzipCompression());
|
||||
}
|
||||
|
||||
public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, ExecutorService savingExecutor, boolean useGzip) {
|
||||
public HiresModelManager(Path fileRoot, HiresModelRenderer renderer, Vector2i tileSize, Vector2i gridOrigin, boolean useGzip) {
|
||||
this.fileRoot = fileRoot;
|
||||
this.renderer = renderer;
|
||||
|
||||
this.tileSize = tileSize;
|
||||
this.gridOrigin = gridOrigin;
|
||||
|
||||
this.savingExecutor = savingExecutor;
|
||||
this.useGzip = useGzip;
|
||||
}
|
||||
|
||||
@ -87,7 +83,7 @@ public HiresModel render(WorldTile tile) {
|
||||
|
||||
private void save(final HiresModel model) {
|
||||
final String modelJson = model.toBufferGeometry().toJson();
|
||||
savingExecutor.submit(() -> save(model, modelJson));
|
||||
save(model, modelJson);
|
||||
}
|
||||
|
||||
private void save(HiresModel model, String modelJson){
|
||||
|
@ -126,6 +126,7 @@ public void save(File file, boolean force, boolean useGzip) throws IOException {
|
||||
PrintWriter pw = new PrintWriter(osw);
|
||||
){
|
||||
pw.print(json);
|
||||
pw.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -195,7 +195,16 @@ private LowresModel getModel(UUID world, Vector2i tile) {
|
||||
model = new CachedModel(world, tile, BufferGeometry.fromJson(json));
|
||||
} catch (IllegalArgumentException | IOException ex){
|
||||
Logger.global.logError("Failed to load lowres model: " + modelFile, ex);
|
||||
|
||||
modelFile.delete();
|
||||
|
||||
/*
|
||||
File brokenFile = modelFile.toPath().getParent().resolve(modelFile.getName() + ".broken").toFile();
|
||||
if (brokenFile.exists()) brokenFile.delete();
|
||||
if (!modelFile.renameTo(brokenFile)) {
|
||||
modelFile.delete();
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ export default class BlueMap {
|
||||
this.skyColor = {
|
||||
value: new Vector3(0, 0, 0)
|
||||
};
|
||||
this.debugInfo = false;
|
||||
|
||||
this.ui = new UI(this);
|
||||
|
||||
@ -139,6 +140,7 @@ export default class BlueMap {
|
||||
this.loadLowresTile,
|
||||
this.lowresScene,
|
||||
this.settings.maps[this.map]['lowres']['tileSize'],
|
||||
this.settings.maps[this.map]['lowres']['translate'],
|
||||
startPos
|
||||
);
|
||||
|
||||
@ -148,6 +150,7 @@ export default class BlueMap {
|
||||
this.loadHiresTile,
|
||||
this.hiresScene,
|
||||
this.settings.maps[this.map]['hires']['tileSize'],
|
||||
this.settings.maps[this.map]['hires']['translate'],
|
||||
startPos
|
||||
);
|
||||
|
||||
@ -349,6 +352,7 @@ export default class BlueMap {
|
||||
this.quality = this.loadUserSetting("renderQuality", this.quality);
|
||||
this.hiresViewDistance = this.loadUserSetting("hiresViewDistance", this.hiresViewDistance);
|
||||
this.lowresViewDistance = this.loadUserSetting("lowresViewDistance", this.lowresViewDistance);
|
||||
this.debugInfo = this.loadUserSetting("debugInfo", this.debugInfo);
|
||||
}
|
||||
|
||||
saveUserSettings(){
|
||||
@ -361,6 +365,7 @@ export default class BlueMap {
|
||||
this.saveUserSetting("renderQuality", this.quality);
|
||||
this.saveUserSetting("hiresViewDistance", this.hiresViewDistance);
|
||||
this.saveUserSetting("lowresViewDistance", this.lowresViewDistance);
|
||||
this.saveUserSetting("debugInfo", this.debugInfo);
|
||||
}
|
||||
|
||||
loadUserSetting(key, defaultValue){
|
||||
|
@ -100,6 +100,7 @@ export default class Controls {
|
||||
|
||||
this.keyStates = {};
|
||||
this.state = Controls.STATES.NONE;
|
||||
this.mouseMoved = false;
|
||||
|
||||
let canvas = $(this.element).find('canvas').get(0);
|
||||
|
||||
@ -116,6 +117,7 @@ export default class Controls {
|
||||
|
||||
// touch events
|
||||
this.hammer = new Hammer.Manager(canvas);
|
||||
let touchTap = new Hammer.Tap({ event: 'tap', pointers: 1, taps: 1, threshold: 2 });
|
||||
let touchMove = new Hammer.Pan({ event: 'move', direction: Hammer.DIRECTION_ALL, threshold: 0 });
|
||||
let touchTilt = new Hammer.Pan({ event: 'tilt', direction: Hammer.DIRECTION_VERTICAL, pointers: 2, threshold: 0 });
|
||||
let touchRotate = new Hammer.Rotate({ event: 'rotate', pointers: 2, threshold: 10 });
|
||||
@ -125,6 +127,7 @@ export default class Controls {
|
||||
touchTilt.recognizeWith(touchZoom);
|
||||
touchRotate.recognizeWith(touchZoom);
|
||||
|
||||
this.hammer.add( touchTap );
|
||||
this.hammer.add( touchMove );
|
||||
this.hammer.add( touchTilt );
|
||||
this.hammer.add( touchRotate );
|
||||
@ -144,6 +147,7 @@ export default class Controls {
|
||||
this.hammer.on('rotatecancel', this.onTouchRotateUp);
|
||||
this.hammer.on('zoomstart', this.onTouchZoomDown);
|
||||
this.hammer.on('zoommove', this.onTouchZoomMove);
|
||||
this.hammer.on('tap', this.onInfoClick);
|
||||
|
||||
this.camera.position.set(0, 1000, 0);
|
||||
this.camera.lookAt(this.position);
|
||||
@ -429,4 +433,11 @@ export default class Controls {
|
||||
onKeyUp = event => {
|
||||
this.keyStates[event.keyCode] = false;
|
||||
};
|
||||
|
||||
onInfoClick = event => {
|
||||
$(document).trigger({
|
||||
type: 'bluemap-info-click',
|
||||
pos: event.center
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -30,9 +30,10 @@ import Tile from './Tile.js';
|
||||
import { hashTile } from './utils.js';
|
||||
|
||||
export default class TileManager {
|
||||
constructor(blueMap, viewDistance, tileLoader, scene, tileSize, position) {
|
||||
constructor(blueMap, viewDistance, tileLoader, scene, tileSize, tileOffset, position) {
|
||||
this.blueMap = blueMap;
|
||||
this.tileSize = new Vector2(tileSize.x, tileSize.z);
|
||||
this.tileOffset = new Vector2(tileOffset.x, tileOffset.z);
|
||||
this.setViewDistance(viewDistance);
|
||||
this.tileLoader = tileLoader;
|
||||
this.scene = scene;
|
||||
@ -54,7 +55,7 @@ export default class TileManager {
|
||||
}
|
||||
|
||||
setPosition(center) {
|
||||
this.tile.set(center.x, center.z).divide(this.tileSize).floor();
|
||||
this.tile.set(center.x, center.z).sub(this.tileOffset).divide(this.tileSize).floor();
|
||||
|
||||
if (!this.tile.equals(this.lastTile) && !this.closed) {
|
||||
this.update();
|
||||
|
138
BlueMapCore/src/main/webroot/js/libs/modules/HudInfo.js
Normal file
138
BlueMapCore/src/main/webroot/js/libs/modules/HudInfo.js
Normal file
@ -0,0 +1,138 @@
|
||||
import $ from 'jquery';
|
||||
import {
|
||||
Raycaster,
|
||||
Vector2
|
||||
} from 'three';
|
||||
import {pathFromCoords} from "../utils";
|
||||
|
||||
export default class HudInfo {
|
||||
|
||||
constructor(blueMap, container){
|
||||
this.blueMap = blueMap;
|
||||
this.container = container;
|
||||
|
||||
this.rayPosition = new Vector2();
|
||||
this.raycaster = new Raycaster();
|
||||
|
||||
this.element = $(`
|
||||
<div class="hud-info" style="display: none">
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
`).appendTo(this.container);
|
||||
|
||||
$(document).on('bluemap-info-click', this.onShowInfo);
|
||||
$(window).on('mousedown wheel', this.onHideInfo);
|
||||
}
|
||||
|
||||
onShowInfo = event => {
|
||||
this.rayPosition.x = ( event.pos.x / this.blueMap.element.offsetWidth ) * 2 - 1;
|
||||
this.rayPosition.y = - ( event.pos.y / this.blueMap.element.offsetHeight ) * 2 + 1;
|
||||
|
||||
this.raycaster.setFromCamera(this.rayPosition, this.blueMap.camera);
|
||||
let hiresData = true;
|
||||
let intersects = this.raycaster.intersectObjects( this.blueMap.hiresScene.children );
|
||||
if (intersects.length === 0){
|
||||
hiresData = false;
|
||||
intersects = this.raycaster.intersectObjects( this.blueMap.lowresScene.children );
|
||||
}
|
||||
|
||||
if (intersects.length > 0) {
|
||||
this.element.hide();
|
||||
let content = this.element.find(".content");
|
||||
content.html("");
|
||||
|
||||
if (this.blueMap.debugInfo){
|
||||
console.debug("Tapped position data: ", intersects[0]);
|
||||
}
|
||||
|
||||
//clicked position
|
||||
let point = intersects[0].point;
|
||||
let normal = intersects[0].face.normal;
|
||||
let block = {
|
||||
x: Math.floor(point.x - normal.x * 0.001),
|
||||
y: Math.floor(point.y - normal.y * 0.001),
|
||||
z: Math.floor(point.z - normal.z * 0.001),
|
||||
};
|
||||
if (hiresData) {
|
||||
$(`
|
||||
<div class="label">block:</div>
|
||||
<div class="coords block">
|
||||
<div class="coord"><span class="label">x</span><span class="value">${block.x}</span></div>
|
||||
<div class="coord"><span class="label">y</span><span class="value">${block.y}</span></div>
|
||||
<div class="coord"><span class="label">z</span><span class="value">${block.z}</span></div>
|
||||
</div>
|
||||
`).appendTo(content);
|
||||
} else {
|
||||
$(`
|
||||
<div class="label">position:</div>
|
||||
<div class="coords block">
|
||||
<div class="coord"><span class="label">x</span><span class="value">${block.x}</span></div>
|
||||
<div class="coord"><span class="label">z</span><span class="value">${block.z}</span></div>
|
||||
</div>
|
||||
`).appendTo(content);
|
||||
}
|
||||
|
||||
//find light-data
|
||||
if (hiresData) {
|
||||
let vecIndex = intersects[0].face.a;
|
||||
let attributes = intersects[0].object.geometry.attributes;
|
||||
let sunlight = attributes.sunlight.array[vecIndex * attributes.sunlight.itemSize];
|
||||
let blocklight = attributes.blocklight.array[vecIndex * attributes.blocklight.itemSize];
|
||||
|
||||
$(`
|
||||
<div class="label" data-show="light">light:</div>
|
||||
<div class="coords block">
|
||||
<div class="coord"><span class="label">sun</span><span class="value">${sunlight}</span></div>
|
||||
<div class="coord"><span class="label">block</span><span class="value">${blocklight}</span></div>
|
||||
</div>
|
||||
`).appendTo(content);
|
||||
}
|
||||
|
||||
if (this.blueMap.debugInfo) {
|
||||
//hires tile path
|
||||
let hiresTileSize = this.blueMap.settings.maps[this.blueMap.map]['hires']['tileSize'];
|
||||
hiresTileSize.y = hiresTileSize.z;
|
||||
let hiresTileOffset = this.blueMap.settings.maps[this.blueMap.map]['hires']['translate'];
|
||||
hiresTileOffset.y = hiresTileOffset.z;
|
||||
let hiresTile = new Vector2(block.x, block.z).sub(hiresTileOffset).divide(hiresTileSize).floor();
|
||||
let hrpath = this.blueMap.dataRoot + this.blueMap.map + '/hires/';
|
||||
hrpath += pathFromCoords(hiresTile.x, hiresTile.y);
|
||||
hrpath += '.json';
|
||||
|
||||
//lowres tile path
|
||||
let lowresTileSize = this.blueMap.settings.maps[this.blueMap.map]['lowres']['tileSize'];
|
||||
lowresTileSize.y = lowresTileSize.z;
|
||||
let lowresTileOffset = this.blueMap.settings.maps[this.blueMap.map]['lowres']['translate'];
|
||||
lowresTileOffset.y = lowresTileOffset.z;
|
||||
let lowresTile = new Vector2(block.x, block.z).sub(lowresTileOffset).divide(lowresTileSize).floor();
|
||||
let lrpath = this.blueMap.dataRoot + this.blueMap.map + '/lowres/';
|
||||
lrpath += pathFromCoords(lowresTile.x, lowresTile.y);
|
||||
lrpath += '.json';
|
||||
$(`
|
||||
<div class="files">
|
||||
<span class="value">${hrpath}</span><br>
|
||||
<span class="value">${lrpath}</span>
|
||||
</div>
|
||||
`).appendTo(content);
|
||||
}
|
||||
|
||||
//display the element
|
||||
this.element.css('left', `${event.pos.x}px`);
|
||||
this.element.css('top', `${event.pos.y}px`);
|
||||
if (event.pos.y < this.blueMap.element.offsetHeight / 3){
|
||||
this.element.addClass("below");
|
||||
} else {
|
||||
this.element.removeClass("below");
|
||||
}
|
||||
this.element.fadeIn(200);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
onHideInfo = event => {
|
||||
if (!this.element.is(':animated')) {
|
||||
this.element.fadeOut(200);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
@ -46,7 +46,7 @@ vec3 lerp(vec3 v1, vec3 v2, float amount){
|
||||
}
|
||||
|
||||
bool mobSpawnColor() {
|
||||
if (vBlocklight < 7.1){
|
||||
if (vBlocklight < 7.1 && vNormal.y > 0.8){
|
||||
float cross1 = vUv.x - vUv.y;
|
||||
float cross2 = vUv.x - (1.0 - vUv.y);
|
||||
return cross1 < 0.05 && cross1 > -0.05 || cross2 < 0.05 && cross2 > -0.05;
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
|
||||
import Button from '../ui/Button.js';
|
||||
import Button from './Button.js';
|
||||
|
||||
import COMPASS from '../../../assets/compass.svg';
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
|
||||
import Dropdown from "../ui/Dropdown";
|
||||
import Dropdown from "./Dropdown";
|
||||
|
||||
export default class MapSelection extends Dropdown {
|
||||
constructor(bluemap) {
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
|
||||
import ToggleButton from '../ui/ToggleButton.js';
|
||||
import ToggleButton from './ToggleButton.js';
|
||||
|
||||
import BURGER from '../../../assets/burger.svg';
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
import $ from 'jquery';
|
||||
|
||||
import Element from "../ui/Element";
|
||||
import Element from "./Element";
|
||||
|
||||
export default class Position extends Element {
|
||||
constructor(blueMap, axis) {
|
@ -29,15 +29,16 @@ import Menu from './Menu.js';
|
||||
import Dropdown from "./Dropdown";
|
||||
import Separator from "./Separator";
|
||||
import Label from "./Label";
|
||||
import MenuButton from '../modules/MenuButton.js';
|
||||
import Compass from "../modules/Compass";
|
||||
import Position from "../modules/Position";
|
||||
import MenuButton from './MenuButton.js';
|
||||
import Compass from "./Compass";
|
||||
import Position from "./Position";
|
||||
import Button from "./Button";
|
||||
import Slider from "./Slider";
|
||||
import ToggleButton from "./ToggleButton";
|
||||
import MapSelection from "../modules/MapSeletion";
|
||||
import MapSelection from "./MapSeletion";
|
||||
|
||||
import NIGHT from '../../../assets/night.svg';
|
||||
import HudInfo from "../modules/HudInfo";
|
||||
|
||||
export default class UI {
|
||||
|
||||
@ -52,6 +53,9 @@ export default class UI {
|
||||
|
||||
this.toolbar = new Toolbar();
|
||||
this.toolbar.element.appendTo(this.hud);
|
||||
|
||||
//modules
|
||||
this.hudInfo = new HudInfo(this.blueMap, this.element);
|
||||
}
|
||||
|
||||
load() {
|
||||
@ -87,6 +91,9 @@ export default class UI {
|
||||
this.blueMap.lowresTileManager.setViewDistance(this.blueMap.lowresViewDistance);
|
||||
this.blueMap.lowresTileManager.update();
|
||||
});
|
||||
let debugInfo = new ToggleButton("debug-info", this.blueMap.debugInfo, button => {
|
||||
this.blueMap.debugInfo = button.isSelected();
|
||||
});
|
||||
|
||||
//toolbar
|
||||
this.toolbar.addElement(menuButton);
|
||||
@ -109,6 +116,8 @@ export default class UI {
|
||||
this.menu.addElement(hiresSlider);
|
||||
this.menu.addElement(new Label('lowres render-distance (blocks):'));
|
||||
this.menu.addElement(lowresSlider);
|
||||
this.menu.addElement(new Separator());
|
||||
this.menu.addElement(debugInfo);
|
||||
this.menu.update();
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ export const splitNumberToPath = num => {
|
||||
path += '-';
|
||||
}
|
||||
|
||||
let s = num.toString();
|
||||
let s = parseInt(num).toString();
|
||||
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
path += s.charAt(i) + '/';
|
||||
|
89
BlueMapCore/src/main/webroot/style/modules/hudInfo.scss
Normal file
89
BlueMapCore/src/main/webroot/style/modules/hudInfo.scss
Normal file
@ -0,0 +1,89 @@
|
||||
.bluemap-container .ui .hud-info {
|
||||
position: absolute;
|
||||
|
||||
transform: translate(-50%, calc(-100% - 1rem));
|
||||
|
||||
background-color: $normal_bg;
|
||||
filter: drop-shadow(1px 1px 3px #0008);
|
||||
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
|
||||
&.below {
|
||||
transform: translate(-50%, 1rem);
|
||||
}
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
|
||||
> .label {
|
||||
min-height: 0;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.5rem 0.5rem 0 1rem;
|
||||
line-height: 0.8rem;
|
||||
color: $label_fg;
|
||||
border-top: solid 1px $line_color;
|
||||
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
> * {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.coords {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
> .coord {
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.2rem;
|
||||
|
||||
border-radius: 0.2rem;
|
||||
|
||||
//background-color: #ccc;
|
||||
|
||||
> .label {
|
||||
color: $label_fg;
|
||||
margin-right: 0.2rem;
|
||||
|
||||
&::after {
|
||||
content: ':';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .files {
|
||||
border-top: solid 1px $line_color;
|
||||
font-size: 0.8rem;
|
||||
line-height: 0.8rem;
|
||||
color: $label_fg;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
|
||||
position: absolute;
|
||||
bottom: -1rem;
|
||||
left: calc(50% - 0.5rem);
|
||||
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
z-index: 0;
|
||||
|
||||
border: solid 0.5rem;
|
||||
border-color: $normal_bg transparent transparent transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.below .content::after {
|
||||
top: -1rem;
|
||||
|
||||
border: solid 0.5rem;
|
||||
border-color: transparent transparent $normal_bg transparent;
|
||||
}
|
||||
}
|
@ -100,4 +100,6 @@ html, body {
|
||||
@import "ui/separator";
|
||||
@import "ui/dropdown";
|
||||
@import "ui/label";
|
||||
@import "modules/position";
|
||||
@import "ui/position";
|
||||
|
||||
@import "modules/hudInfo";
|
||||
|
Loading…
Reference in New Issue
Block a user