🚶 Floorplan & structure CSS

This commit is contained in:
duckietm 2025-03-19 10:54:39 +01:00
parent d487102236
commit 141d4bc68a
22 changed files with 1229 additions and 3423 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,856 +0,0 @@
.bubble-container {
transition: top 0.2s ease 0s;
.chat-bubble {
border-image-slice: 17 6 6 29 fill;
border-image-width: 17px 6px 6px 29px;
border-image-outset: 2px 0px 0px 0px;
border-image-repeat: repeat repeat;
&.type-0 {
// normal
.message {
font-weight: 400;
}
}
&.type-1 {
// whisper
.message {
font-weight: 400;
font-style: italic;
color: #595959;
}
}
&.type-2 {
// shout
.message {
font-weight: 700;
}
}
&.bubble-0 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_0_transparent.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
bottom: -5px;
}
}
&.bubble-1 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_1.png');
border-image-slice: 18 6 6 29 fill;
border-image-width: 18px 6px 6px 29px;
border-image-outset: 3px 0px 0px 0px;
.user-container {
display: none;
}
.username {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-2,
&.bubble-31 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_2.png');
.user-container {
display: none;
}
.username {
color: rgba($white, 1);
}
.message {
color: rgba($white, 1) !important;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_2_31_pointer.png');
height: 7px;
}
}
&.bubble-3 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_3.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_3_pointer.png');
}
}
&.bubble-4 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_4.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_4_pointer.png');
}
}
&.bubble-5 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_5.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_5_pointer.png');
}
}
&.bubble-6 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_6.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_6_pointer.png');
}
}
&.bubble-7 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_7.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_7_pointer.png');
}
}
&.bubble-8 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_8.png');
border-image-slice: 20 6 6 27 fill;
border-image-width: 20px 6px 6px 27px;
border-image-outset: 5px 0px 0px 0px;
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_8_pointer.png');
}
}
&.bubble-9 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_9.png');
border-image-slice: 17 18 12 19 fill;
border-image-width: 17px 18px 12px 19px;
border-image-outset: 7px 7px 0px 9px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_9_pointer.png');
width: 7px;
height: 10px;
bottom: -6px;
}
}
&.bubble-10 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_10.png');
border-image-slice: 29 18 8 37 fill;
border-image-width: 29px 18px 8px 37px;
border-image-outset: 12px 7px 1px 5px;
.chat-content {
margin-left: 24px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_10_pointer.png');
width: 7px;
height: 8px;
bottom: -3px;
}
}
&.bubble-11 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_11.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_11_pointer.png');
}
}
&.bubble-12 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_12.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_12_pointer.png');
}
}
&.bubble-13 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_13.png');
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_13_pointer.png');
}
}
&.bubble-14 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_14.png');
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_14_pointer.png');
}
}
&.bubble-15 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_15.png');
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_15_pointer.png');
}
}
&.bubble-16 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_16.png');
border-image-slice: 13 6 10 31 fill;
border-image-width: 13px 6px 10px 31px;
border-image-outset: 6px 0px 0px 0px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_16_pointer.png');
height: 8px;
}
}
&.bubble-17 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_17.png');
border-image-slice: 24 6 8 35 fill;
border-image-width: 24px 6px 8px 35px;
border-image-outset: 9px 0px 2px 5px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_17_pointer.png');
}
}
&.bubble-18 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_18.png');
border-image-slice: 7 16 8 16 fill;
border-image-width: 7px 16px 8px 16px;
border-image-outset: 3px 10px 2px 11px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_18_pointer.png');
height: 8px;
}
}
&.bubble-19 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_19.png');
border-image-slice: 17 6 9 19 fill;
border-image-width: 17px 6px 9px 19px;
border-image-outset: 5px 0px 0px 8px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_19_20_pointer.png');
}
}
&.bubble-20 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_20.png');
border-image-slice: 18 6 8 19 fill;
border-image-width: 18px 6px 8px 19px;
border-image-outset: 5px 0px 0px 8px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_19_20_pointer.png');
}
}
&.bubble-21 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_21.png');
border-image-slice: 20 6 12 24 fill;
border-image-width: 20px 6px 12px 24px;
border-image-outset: 13px 2px 1px 3px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_21_pointer.png');
bottom: -4px;
}
}
&.bubble-22 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_22.png');
border-image-slice: 18 19 11 33 fill;
border-image-width: 18px 19px 11px 33px;
border-image-outset: 7px 1px 1px 5px;
.chat-content {
margin-left: 20px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_22_pointer.png');
}
}
&.bubble-23 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_23.png');
border-image-slice: 16 6 7 32 fill;
border-image-width: 16px 6px 7px 32px;
border-image-outset: 5px 0px 0px 3px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_23_37_pointer.png');
}
}
&.bubble-24 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_24.png');
border-image-slice: 23 8 6 40 fill;
border-image-width: 23px 8px 6px 40px;
border-image-outset: 6px 0px 0px 6px;
.chat-content {
margin-left: 30px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_24_pointer.png');
bottom: -4px;
}
}
&.bubble-25 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_25.png');
border-image-slice: 10 13 8 28 fill;
border-image-width: 10px 13px 8px 28px;
border-image-outset: 6px 3px 2px 0px;
.chat-content {
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_25_pointer.png');
height: 9px;
bottom: -7px;
}
}
&.bubble-26 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_26.png');
border-image-slice: 16 9 8 29 fill;
border-image-width: 16px 9px 8px 29px;
border-image-outset: 2px 2px 2px 0px;
.chat-content {
color: #c59432;
text-shadow: 1px 1px rgba(0, 0, 0, 0.3);
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_26_pointer.png');
height: 10px;
bottom: -6px;
}
}
&.bubble-27 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_27.png');
border-image-slice: 25 6 5 36 fill;
border-image-width: 25px 6px 5px 36px;
border-image-outset: 8px 0px 0px 5px;
.chat-content {
margin-left: 30px;
color: #fff;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_27_pointer.png');
}
}
&.bubble-28 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_28.png');
border-image-slice: 16 7 7 27 fill;
border-image-width: 16px 7px 7px 27px;
border-image-outset: 3px 0px 0px 0px;
.chat-content {
margin-left: 25px;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_28_pointer.png');
}
}
&.bubble-29 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_29.png');
border-image-slice: 10 7 15 31 fill;
border-image-width: 10px 7px 15px 31px;
border-image-outset: 2px 0px 0px 1px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_29_pointer.png');
bottom: -4px;
}
}
&.bubble-30 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_30.png');
.user-container {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_30_pointer.png');
height: 7px;
}
}
&.bubble-32 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_32.png');
border-image-slice: 15 7 7 30 fill;
border-image-width: 15px 7px 7px 30px;
border-image-outset: 2px 0px 0px 0px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_32_pointer.png');
}
}
&.bubble-33 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
border-image-slice: 7 6 6 39 fill;
border-image-width: 7px 6px 6px 39px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
.chat-content {
margin-left: 35px;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 9px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_33_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-34 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
border-image-slice: 7 6 6 39 fill;
border-image-width: 7px 6px 6px 39px;
border-image-outset: 2px 0px 0px 0px;
&.type-1 {
.message {
font-style: unset;
color: inherit;
}
}
.user-container {
display: none;
}
.username {
display: none;
}
.chat-content {
margin-left: 35px;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 9px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_34_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_0_1_33_34_pointer.png');
}
}
&.bubble-35 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_35.png');
border-image-slice: 19 6 5 29 fill;
border-image-width: 19px 6px 5px 29px;
border-image-outset: 4px 0px 0px 0px;
.user-container {
display: none;
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_35_pointer.png');
}
}
&.bubble-36 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_36.png');
border-image-slice: 17 7 5 30 fill;
border-image-width: 17px 7px 5px 30px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
&::before {
content: ' ';
position: absolute;
width: 13px;
height: 18px;
left: 5px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_36_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_36_pointer.png');
}
}
&.bubble-37 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_37.png');
border-image-slice: 16 6 7 32 fill;
border-image-width: 16px 6px 7px 32px;
border-image-outset: 5px 0px 0px 3px;
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_23_37_pointer.png');
}
}
&.bubble-38 {
border-image-source: url('@/assets/images/chat/chatbubbles/bubble_38.png');
border-image-slice: 17 7 5 30 fill;
border-image-width: 17px 7px 5px 30px;
border-image-outset: 2px 0px 0px 0px;
.user-container {
display: none;
}
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 3px;
top: 2px;
background: url('@/assets/images/chat/chatbubbles/bubble_38_extra.png');
}
.pointer {
background: url('@/assets/images/chat/chatbubbles/bubble_38_pointer.png');
}
}
.user-container {
z-index: 3;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
max-height: 24px;
overflow: hidden;
.user-image {
position: absolute;
top: -15px;
left: -9.25px;
width: 45px;
height: 65px;
background-repeat: no-repeat;
background-position: center;
transform: scale(0.5);
overflow: hidden;
image-rendering: initial;
}
}
.chat-content {
padding: 5px 6px 5px 4px;
margin-left: 27px;
line-height: 1;
color: $black;
min-height: 25px;
}
}
}
.chat-bubble-icon {
background-repeat: no-repeat;
background-position: center;
&.bubble-0 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_0.png');
}
&.bubble-1 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_1.png');
height: 25px;
}
&.bubble-2,
&.bubble-31 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_2.png');
}
&.bubble-3 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_3.png');
}
&.bubble-4 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_4.png');
}
&.bubble-5 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_5.png');
}
&.bubble-6 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_6.png');
}
&.bubble-7 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_7.png');
}
&.bubble-8 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_8.png');
}
&.bubble-9 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_9.png');
}
&.bubble-10 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_10.png');
}
&.bubble-11 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_11.png');
}
&.bubble-12 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_12.png');
}
&.bubble-13 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_13.png');
}
&.bubble-14 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_14.png');
}
&.bubble-15 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_15.png');
}
&.bubble-16 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_16.png');
}
&.bubble-17 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_17.png');
}
&.bubble-18 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_18.png');
}
&.bubble-19 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_19.png');
}
&.bubble-20 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_20.png');
}
&.bubble-21 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_21.png');
}
&.bubble-22 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_22.png');
}
&.bubble-23 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_23.png');
}
&.bubble-24 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_24.png');
}
&.bubble-25 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_25.png');
}
&.bubble-26 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_26.png');
}
&.bubble-27 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_27.png');
}
&.bubble-28 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_28.png');
}
&.bubble-29 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_29.png');
}
&.bubble-30 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_30.png');
}
&.bubble-32 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_32.png');
}
&.bubble-33 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_33_extra.png');
}
}
&.bubble-34 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_33_34.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_34_extra.png');
}
}
&.bubble-35 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_35.png');
}
&.bubble-36 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_36.png');
&::before {
content: ' ';
position: absolute;
width: 13px;
height: 18px;
left: 13px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_36_extra.png');
}
}
&.bubble-37 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_35.png');
}
&.bubble-38 {
background-image: url('@/assets/images/chat/chatbubbles/bubble_38.png');
&::before {
content: ' ';
position: absolute;
width: 19px;
height: 19px;
left: 11px;
top: 10px;
background: url('@/assets/images/chat/chatbubbles/bubble_38_extra.png');
}
}
}

21
src/common/Slider.tsx Normal file
View File

@ -0,0 +1,21 @@
import { FC } from 'react';
import ReactSlider, { ReactSliderProps } from 'react-slider';
import { Button } from './Button';
import { Flex } from './Flex';
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
export interface SliderProps extends ReactSliderProps
{
disabledButton?: boolean;
}
export const Slider: FC<SliderProps> = props =>
{
const { disabledButton, max, min, value, onChange, ...rest } = props;
return <Flex fullWidth gap={ 1 }>
{ !disabledButton && <Button disabled={ min >= value } onClick={ () => onChange(min < value ? value - 1 : min, 0) }><FaAngleLeft /></Button> }
<ReactSlider className={ 'nitro-slider' } max={ max } min={ min } value={ value } onChange={ onChange } { ...rest } />
{ !disabledButton && <Button disabled={ max <= value } onClick={ () => onChange(max > value ? value + 1 : max, 0) }><FaAngleRight /></Button> }
</Flex>;
}

View File

@ -18,4 +18,5 @@ export * from './draggable-window';
export * from './layout'; export * from './layout';
export * from './layout/limited-edition'; export * from './layout/limited-edition';
export * from './types'; export * from './types';
export * from "./Slider";
export * from './utils'; export * from './utils';

View File

@ -1,7 +1,7 @@
import { AddLinkEventTracker, FloorHeightMapEvent, ILinkEventTracker, RemoveLinkEventTracker, RoomEngineEvent, RoomVisualizationSettingsEvent, UpdateFloorPropertiesMessageComposer } from '@nitrots/nitro-renderer'; import { AddLinkEventTracker, FloorHeightMapEvent, ILinkEventTracker, RemoveLinkEventTracker, RoomEngineEvent, RoomVisualizationSettingsEvent, UpdateFloorPropertiesMessageComposer } from '@nitrots/nitro-renderer';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { LocalizeText, SendMessageComposer } from '../../api'; import { LocalizeText, SendMessageComposer } from '../../api';
import { Button, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common'; import { Button, ButtonGroup, Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../common';
import { useMessageEvent, useNitroEvent } from '../../hooks'; import { useMessageEvent, useNitroEvent } from '../../hooks';
import { FloorplanEditorContextProvider } from './FloorplanEditorContext'; import { FloorplanEditorContextProvider } from './FloorplanEditorContext';
import { FloorplanEditor } from './common/FloorplanEditor'; import { FloorplanEditor } from './common/FloorplanEditor';
@ -43,7 +43,7 @@ export const FloorplanEditorView: FC<{}> = props =>
convertNumbersForSaving(visualizationSettings.thicknessFloor), convertNumbersForSaving(visualizationSettings.thicknessFloor),
(visualizationSettings.wallHeight - 1) (visualizationSettings.wallHeight - 1)
)); ));
}; }
const revertChanges = () => const revertChanges = () =>
{ {
@ -54,7 +54,7 @@ export const FloorplanEditorView: FC<{}> = props =>
FloorplanEditor.instance.renderTiles(); FloorplanEditor.instance.renderTiles();
}; };
useNitroEvent<RoomEngineEvent>(RoomEngineEvent.DISPOSED, event => setIsVisible(false)); useNitroEvent<RoomEngineEvent>(RoomEngineEvent.DISPOSED, event => setIsVisible(false));
useMessageEvent<FloorHeightMapEvent>(FloorHeightMapEvent, event => useMessageEvent<FloorHeightMapEvent>(FloorHeightMapEvent, event =>
{ {
@ -138,23 +138,23 @@ export const FloorplanEditorView: FC<{}> = props =>
return ( return (
<FloorplanEditorContextProvider value={ { originalFloorplanSettings: originalFloorplanSettings, setOriginalFloorplanSettings: setOriginalFloorplanSettings, visualizationSettings: visualizationSettings, setVisualizationSettings: setVisualizationSettings } }> <FloorplanEditorContextProvider value={ { originalFloorplanSettings: originalFloorplanSettings, setOriginalFloorplanSettings: setOriginalFloorplanSettings, visualizationSettings: visualizationSettings, setVisualizationSettings: setVisualizationSettings } }>
{ isVisible && { isVisible &&
<NitroCardView className="w-[760px] h-[500px]" theme="primary-slim" uniqueKey="floorpan-editor"> <NitroCardView uniqueKey="floorpan-editor" className="nitro-floorplan-editor" theme="primary-slim">
<NitroCardHeaderView headerText={ LocalizeText('floor.plan.editor.title') } onCloseClick={ () => setIsVisible(false) } /> <NitroCardHeaderView headerText={ LocalizeText('floor.plan.editor.title') } onCloseClick={ () => setIsVisible(false) } />
<NitroCardContentView overflow="hidden"> <NitroCardContentView overflow="hidden">
<FloorplanOptionsView /> <FloorplanOptionsView />
<FloorplanCanvasView overflow="hidden" /> <FloorplanCanvasView overflow="hidden" />
<div className="flex justify-between"> <Flex justifyContent="between">
<Button onClick={ revertChanges }>{ LocalizeText('floor.plan.editor.reload') }</Button> <Button onClick={ revertChanges }>{ LocalizeText('floor.plan.editor.reload') }</Button>
<div className="relative inline-flex align-middle"> <ButtonGroup>
<Button disabled={ true }>{ LocalizeText('floor.plan.editor.preview') }</Button> <Button disabled={ true }>{ LocalizeText('floor.plan.editor.preview') }</Button>
<Button onClick={ event => setImportExportVisible(true) }>{ LocalizeText('floor.plan.editor.import.export') }</Button> <Button onClick={ event => setImportExportVisible(true) }>{ LocalizeText('floor.plan.editor.import.export') }</Button>
<Button onClick={ saveFloorChanges }>{ LocalizeText('floor.plan.editor.save') }</Button> <Button onClick={ saveFloorChanges }>{ LocalizeText('floor.plan.editor.save') }</Button>
</div> </ButtonGroup>
</div> </Flex>
</NitroCardContentView> </NitroCardContentView>
</NitroCardView> } </NitroCardView> }
{ importExportVisible && { importExportVisible &&
<FloorplanImportExportView onCloseClick={ () => setImportExportVisible(false) } /> } <FloorplanImportExportView onCloseClick={ () => setImportExportVisible(false) } /> }
</FloorplanEditorContextProvider> </FloorplanEditorContextProvider>
); );
}; }

View File

@ -2,10 +2,9 @@ import { ActionSettings } from './ActionSettings';
import { FloorAction, HEIGHT_SCHEME, MAX_NUM_TILE_PER_AXIS, TILE_SIZE } from './Constants'; import { FloorAction, HEIGHT_SCHEME, MAX_NUM_TILE_PER_AXIS, TILE_SIZE } from './Constants';
import { imageBase64, spritesheet } from './FloorplanResource'; import { imageBase64, spritesheet } from './FloorplanResource';
import { Tile } from './Tile'; import { Tile } from './Tile';
import { getScreenPositionForTile } from './Utils'; import { getScreenPositionForTile, getTileFromScreenPosition } from './Utils';
export class FloorplanEditor export class FloorplanEditor {
{
private static _INSTANCE: FloorplanEditor = null; private static _INSTANCE: FloorplanEditor = null;
public static readonly TILE_BLOCKED = 'r_blocked'; public static readonly TILE_BLOCKED = 'r_blocked';
@ -19,25 +18,24 @@ export class FloorplanEditor
private _lastUsedTile: { x: number, y: number }; private _lastUsedTile: { x: number, y: number };
private _renderer: CanvasRenderingContext2D; private _renderer: CanvasRenderingContext2D;
private _actionSettings: ActionSettings; private _actionSettings: ActionSettings;
private _image: HTMLImageElement; private _image: HTMLImageElement;
private _zoomLevel: number = 1.0;
private _squareSelectMode: boolean = false;
private _selectionStart: { x: number, y: number } | null = null;
private _selectionEnd: { x: number, y: number } | null = null;
constructor() constructor() {
{
const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20; const width = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20;
const height = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100; const height = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100;
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.height = height; canvas.height = height;
canvas.width = width; canvas.width = width;
canvas.style.touchAction = 'none'; canvas.style.touchAction = 'none';
canvas.oncontextmenu = (e) => { e.preventDefault(); }; // Added from old code
this._renderer = canvas.getContext('2d'); this._renderer = canvas.getContext('2d')!;
this._image = new Image(); this._image = new Image();
this._image.src = imageBase64; this._image.src = imageBase64;
this._tilemap = []; this._tilemap = [];
@ -49,69 +47,78 @@ export class FloorplanEditor
this._actionSettings = new ActionSettings(); this._actionSettings = new ActionSettings();
} }
public onPointerRelease(): void public setSquareSelectMode(enabled: boolean): void {
{ this._squareSelectMode = enabled;
this._isPointerDown = false; if (!enabled) {
this._selectionStart = null;
this._selectionEnd = null;
}
} }
public onPointerDown(event: PointerEvent): void public get squareSelectMode(): boolean {
{ return this._squareSelectMode;
if(event.button === 2) return; }
const location = { x: event.offsetX, y: event.offsetY }; public onPointerRelease(): void {
this._isPointerDown = false;
if (this._squareSelectMode && this._selectionStart) {
this.finalizeSquareSelection();
}
}
public onPointerDown(event: PointerEvent): void {
if (this._squareSelectMode) {
event.preventDefault();
const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel };
const [tileX, tileY] = getTileFromScreenPosition(location.x, location.y);
const roundedX = Math.floor(tileX);
const roundedY = Math.floor(tileY);
this._selectionStart = { x: roundedX, y: roundedY };
this._selectionEnd = { x: roundedX, y: roundedY };
this._isPointerDown = true;
return;
}
if (event.button === 2) return;
const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel };
this._isPointerDown = true; this._isPointerDown = true;
this.tileHitDetection(location, true); this.tileHitDetection(location, true);
} }
public onPointerMove(event: PointerEvent): void public onPointerMove(event: PointerEvent): void {
{ if (!this._isPointerDown) return;
if(!this._isPointerDown) return; const location = { x: event.offsetX / this._zoomLevel, y: event.offsetY / this._zoomLevel };
if (this._squareSelectMode && this._selectionStart) {
const location = { x: event.offsetX, y: event.offsetY }; const [tileX, tileY] = getTileFromScreenPosition(location.x, location.y);
this._selectionEnd!.x = Math.floor(tileX);
this._selectionEnd!.y = Math.floor(tileY);
this.renderTiles();
return;
}
this.tileHitDetection(location, false); this.tileHitDetection(location, false);
} }
private tileHitDetection(tempPoint: { x: number, y: number }, isClick: boolean = false): boolean private tileHitDetection(tempPoint: { x: number, y: number }, isClick: boolean = false): boolean {
{
const mousePositionX = Math.floor(tempPoint.x); const mousePositionX = Math.floor(tempPoint.x);
const mousePositionY = Math.floor(tempPoint.y); const mousePositionY = Math.floor(tempPoint.y);
const width = TILE_SIZE; const width = TILE_SIZE;
const height = TILE_SIZE / 2; const height = TILE_SIZE / 2;
for (let y = 0; y < this._tilemap.length; y++) {
for(let y = 0; y < this._tilemap.length; y++) for (let x = 0; x < this._tilemap[y].length; x++) {
{ const [tileStartX, tileStartY] = getScreenPositionForTile(x, y);
for(let x = 0; x < this.tilemap[y].length; x++)
{
const [ tileStartX, tileStartY ] = getScreenPositionForTile(x, y);
const centreX = tileStartX + (width / 2); const centreX = tileStartX + (width / 2);
const centreY = tileStartY + (height / 2); const centreY = tileStartY + (height / 2);
const dx = Math.abs(mousePositionX - centreX); const dx = Math.abs(mousePositionX - centreX);
const dy = Math.abs(mousePositionY - centreY); const dy = Math.abs(mousePositionY - centreY);
const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);
const solution = (dx / (width * 0.5) + dy / (height * 0.5) <= 1);//todo: improve this if (solution) {
if (this._isPointerDown) {
if(solution) if (isClick) {
{
if(this._isPointerDown)
{
if(isClick)
{
this.onClick(x, y); this.onClick(x, y);
} } else if (this._lastUsedTile.x !== x || this._lastUsedTile.y !== y) {
else if(this._lastUsedTile.x !== x || this._lastUsedTile.y !== y)
{
this._lastUsedTile.x = x; this._lastUsedTile.x = x;
this._lastUsedTile.y = y; this._lastUsedTile.y = y;
this.onClick(x, y); this.onClick(x, y);
} }
} }
return true; return true;
} }
@ -120,31 +127,25 @@ export class FloorplanEditor
return false; return false;
} }
private onClick(x: number, y: number): void private onClick(x: number, y: number, render: boolean = true, force: boolean = false): void { // Updated from old code
{
const tile = this._tilemap[y][x]; const tile = this._tilemap[y][x];
const heightIndex = HEIGHT_SCHEME.indexOf(tile.height); let currentHeightIndex = (tile.height === 'x' && force) ? 0 : HEIGHT_SCHEME.indexOf(tile.height);
let futureHeightIndex = 0; let futureHeightIndex = 0;
switch (this._actionSettings.currentAction) {
switch(this._actionSettings.currentAction)
{
case FloorAction.DOOR: case FloorAction.DOOR:
if (!force && tile.height !== 'x') {
if(tile.height !== 'x')
{
this._doorLocation.x = x; this._doorLocation.x = x;
this._doorLocation.y = y; this._doorLocation.y = y;
this.renderTiles(); if (render) this.renderTiles();
} }
return; return;
case FloorAction.UP: case FloorAction.UP:
if(tile.height === 'x') return; if (!force && tile.height === 'x') return;
futureHeightIndex = heightIndex + 1; futureHeightIndex = currentHeightIndex + 1;
break; break;
case FloorAction.DOWN: case FloorAction.DOWN:
if(tile.height === 'x' || (heightIndex <= 1)) return; if (!force && (tile.height === 'x' || (currentHeightIndex <= 1))) return;
futureHeightIndex = heightIndex - 1; futureHeightIndex = currentHeightIndex - 1;
break; break;
case FloorAction.SET: case FloorAction.SET:
futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight); futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight);
@ -153,223 +154,289 @@ export class FloorplanEditor
futureHeightIndex = 0; futureHeightIndex = 0;
break; break;
} }
if (futureHeightIndex === -1) return;
if(futureHeightIndex === -1) return; if (currentHeightIndex === futureHeightIndex) return;
if (!force && futureHeightIndex > 0) {
if(heightIndex === futureHeightIndex) return; if ((x + 1) > this._width) this._width = x + 1;
if ((y + 1) > this._height) this._height = y + 1;
if(futureHeightIndex > 0)
{
if((x + 1) > this._width) this._width = x + 1;
if((y + 1) > this._height) this._height = y + 1;
} }
const newHeight = HEIGHT_SCHEME[futureHeightIndex]; const newHeight = HEIGHT_SCHEME[futureHeightIndex];
if (!newHeight) return;
if(!newHeight) return;
if(tile.isBlocked) return;
this._tilemap[y][x].height = newHeight; this._tilemap[y][x].height = newHeight;
if (render) this.renderTiles();
}
public renderTiles(): void {
this.clearCanvas();
this._renderer.save();
this._renderer.scale(this._zoomLevel, this._zoomLevel);
for (let y = 0; y < this._tilemap.length; y++) {
for (let x = 0; x < this._tilemap[y].length; x++) {
const tile = this._tilemap[y][x];
let assetName = tile.height;
if (this._doorLocation.x === x && this._doorLocation.y === y)
assetName = FloorplanEditor.TILE_DOOR;
if (tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED;
if ((tile.height === 'x' || tile.height === 'X') && tile.isBlocked) assetName = 'x';
const [positionX, positionY] = getScreenPositionForTile(x, y);
const asset = spritesheet.frames[assetName];
if (asset === undefined) {
console.warn(`Asset "${assetName}" not found in spritesheet.`);
continue;
}
this._renderer.drawImage(
this._image,
asset.frame.x,
asset.frame.y,
asset.frame.w,
asset.frame.h,
positionX,
positionY,
asset.frame.w,
asset.frame.h
);
if (this._squareSelectMode && this._isPointerDown && this._selectionStart && this._selectionEnd) {
const selMinX = Math.min(this._selectionStart.x, this._selectionEnd.x);
const selMaxX = Math.max(this._selectionStart.x, this._selectionEnd.x);
const selMinY = Math.min(this._selectionStart.y, this._selectionEnd.y);
const selMaxY = Math.max(this._selectionStart.y, this._selectionEnd.y);
if (x >= selMinX && x <= selMaxX && y >= selMinY && y <= selMaxY) {
this._renderer.fillStyle = 'rgba(0, 255, 0, 0.3)';
this._renderer.fillRect(positionX, positionY, asset.frame.w, asset.frame.h);
continue;
}
}
if (tile.selected) {
this._renderer.fillStyle = tile.isBlocked ? 'rgb(128, 0, 128)' : 'rgba(0, 0, 255, 0.3)';
this._renderer.fillRect(positionX, positionY, asset.frame.w, asset.frame.h);
}
}
}
this._renderer.restore();
}
public toggleSelectAll(): void { // Added from old code
for (let y = 0; y < this._tilemap.length; y++) {
for (let x = 0; x < this._tilemap[y].length; x++) {
this._tilemap[y][x].selected = true;
if (this._actionSettings.currentAction !== FloorAction.DOOR) {
const tile = this._tilemap[y][x];
let currentHeightIndex = tile.height === 'x' ? 0 : HEIGHT_SCHEME.indexOf(tile.height);
let futureHeightIndex = 0;
switch (this._actionSettings.currentAction) {
case FloorAction.UP:
if (tile.height === 'x') continue;
futureHeightIndex = currentHeightIndex + 1;
break;
case FloorAction.DOWN:
if (tile.height === 'x' || currentHeightIndex <= 1) continue;
futureHeightIndex = currentHeightIndex - 1;
break;
case FloorAction.SET:
futureHeightIndex = HEIGHT_SCHEME.indexOf(this._actionSettings.currentHeight);
break;
case FloorAction.UNSET:
futureHeightIndex = 0;
break;
default:
continue;
}
if (futureHeightIndex !== -1 && currentHeightIndex !== futureHeightIndex) {
const newHeight = HEIGHT_SCHEME[futureHeightIndex];
if (newHeight) {
this._tilemap[y][x].height = newHeight;
if ((x + 1) > this._width) this._width = x + 1;
if ((y + 1) > this._height) this._height = y + 1;
}
}
}
}
}
this.recalcActiveArea();
this.renderTiles(); this.renderTiles();
} }
public renderTiles(): void private finalizeSquareSelection(): void { // Updated from old code
{ const startX = Math.floor(this._selectionStart!.x);
this.clearCanvas(); const startY = Math.floor(this._selectionStart!.y);
const endX = Math.floor(this._selectionEnd!.x);
const endY = Math.floor(this._selectionEnd!.y);
const minX = Math.min(startX, endX);
const maxX = Math.max(startX, endX);
const minY = Math.min(startY, endY);
const maxY = Math.max(startY, endY);
this.selectSquareField(minX, minY, maxX, maxY);
this._selectionStart = null;
this._selectionEnd = null;
this.renderTiles();
}
for(let y = 0; y < this._tilemap.length; y++) private selectSquareField(x1: number, y1: number, x2: number, y2: number): void { // Added from old code
{ for (let y = y1; y <= y2; y++) {
for(let x = 0; x < this.tilemap[y].length; x++) for (let x = x1; x <= x2; x++) {
{ if (this._tilemap[y] && this._tilemap[y][x]) {
const tile = this.tilemap[y][x]; this._tilemap[y][x].selected = true;
let assetName = tile.height; this.onClick(x, y, false, true);
}
}
}
this.recalcActiveArea();
this.renderTiles();
}
if(this._doorLocation.x === x && this._doorLocation.y === y) private recalcActiveArea(): void { // Added from old code
assetName = FloorplanEditor.TILE_DOOR; this._width = 0;
this._height = 0;
if(tile.isBlocked) assetName = FloorplanEditor.TILE_BLOCKED; for (let y = 0; y < this._tilemap.length; y++) {
for (let x = 0; x < this._tilemap[y].length; x++) {
//if((tile.height === 'x') || tile.height === 'X') continue; if (this._tilemap[y][x].height !== 'x') {
const [ positionX, positionY ] = getScreenPositionForTile(x, y); if ((x + 1) > this._width) this._width = x + 1;
if ((y + 1) > this._height) this._height = y + 1;
const asset = spritesheet.frames[assetName]; }
this.renderer.drawImage(this._image, asset.frame.x, asset.frame.y, asset.frame.w, asset.frame.h, positionX, positionY, asset.frame.w, asset.frame.h);
} }
} }
} }
public setTilemap(map: string, blockedTiles: boolean[][]): void public setTilemap(map: string, blockedTiles: boolean[][]): void {
{
this._tilemap = []; this._tilemap = [];
const roomMapStringSplit = map.split('\r'); const roomMapStringSplit = map.split('\r');
let width = 0; let width = 0;
let height = roomMapStringSplit.length; let height = roomMapStringSplit.length;
for (let y = 0; y < height; y++) {
// find the map width, height
for(let y = 0; y < height; y++)
{
const originalRow = roomMapStringSplit[y]; const originalRow = roomMapStringSplit[y];
if (originalRow.length === 0) {
if(originalRow.length === 0)
{
roomMapStringSplit.splice(y, 1); roomMapStringSplit.splice(y, 1);
height = roomMapStringSplit.length; height = roomMapStringSplit.length;
y--; y--;
continue; continue;
} }
if (originalRow.length > width) {
if(originalRow.length > width)
{
width = originalRow.length; width = originalRow.length;
} }
} }
// fill map with room heightmap tiles for (let y = 0; y < height; y++) {
for(let y = 0; y < height; y++)
{
this._tilemap[y] = []; this._tilemap[y] = [];
const rowString = roomMapStringSplit[y]; const rowString = roomMapStringSplit[y];
for (let x = 0; x < width; x++) {
for(let x = 0; x < width; x++)
{
const blocked = (blockedTiles[y] && blockedTiles[y][x]) || false; const blocked = (blockedTiles[y] && blockedTiles[y][x]) || false;
const char = rowString[x]; const char = rowString[x];
if(((!(char === 'x')) && (!(char === 'X')) && char)) if ((!(char === 'x')) && (!(char === 'X')) && char) {
{
this._tilemap[y][x] = new Tile(char, blocked); this._tilemap[y][x] = new Tile(char, blocked);
} } else {
else
{
this._tilemap[y][x] = new Tile('x', blocked); this._tilemap[y][x] = new Tile('x', blocked);
} }
} }
for (let x = width; x < MAX_NUM_TILE_PER_AXIS; x++) {
for(let x = width; x < MAX_NUM_TILE_PER_AXIS; x++) this._tilemap[y][x] = new Tile('x', false);
{
this.tilemap[y][x] = new Tile('x', false);
} }
} }
for (let y = height; y < MAX_NUM_TILE_PER_AXIS; y++) {
// fill remaining map with empty tiles if (!this._tilemap[y]) this._tilemap[y] = [];
for(let y = height; y < MAX_NUM_TILE_PER_AXIS; y++) for (let x = 0; x < MAX_NUM_TILE_PER_AXIS; x++) {
{ this._tilemap[y][x] = new Tile('x', false);
if(!this.tilemap[y]) this.tilemap[y] = [];
for(let x = 0; x < MAX_NUM_TILE_PER_AXIS; x++)
{
this.tilemap[y][x] = new Tile('x', false);
} }
} }
this._width = width; this._width = width;
this._height = height; this._height = height;
} }
public getCurrentTilemapString(): string public getCurrentTilemapString(): string {
{
const highestTile = this._tilemap[this._height - 1][this._width - 1]; const highestTile = this._tilemap[this._height - 1][this._width - 1];
if (highestTile.height === 'x') {
if(highestTile.height === 'x')
{
this._width = -1; this._width = -1;
this._height = -1; this._height = -1;
for (let y = MAX_NUM_TILE_PER_AXIS - 1; y >= 0; y--) {
for(let y = MAX_NUM_TILE_PER_AXIS - 1; y >= 0; y--) if (!this._tilemap[y]) continue;
{ for (let x = MAX_NUM_TILE_PER_AXIS - 1; x >= 0; x--) {
if(!this._tilemap[y]) continue; if (!this._tilemap[y][x]) continue;
for(let x = MAX_NUM_TILE_PER_AXIS - 1; x >= 0; x--)
{
if(!this._tilemap[y][x]) continue;
const tile = this._tilemap[y][x]; const tile = this._tilemap[y][x];
if (tile.height !== 'x') {
if(tile.height !== 'x') if ((x + 1) > this._width)
{
if((x + 1) > this._width)
this._width = x + 1; this._width = x + 1;
if ((y + 1) > this._height)
if((y + 1) > this._height)
this._height = y + 1; this._height = y + 1;
} }
} }
} }
} }
const rows = []; const rows = [];
for (let y = 0; y < this._height; y++) {
for(let y = 0; y < this._height; y++)
{
const row = []; const row = [];
for (let x = 0; x < this._width; x++) {
for(let x = 0; x < this._width; x++)
{
const tile = this._tilemap[y][x]; const tile = this._tilemap[y][x];
row[x] = tile.height; row[x] = tile.height;
} }
rows[y] = row.join(''); rows[y] = row.join('');
} }
return rows.join('\r'); return rows.join('\r');
} }
public clear(): void public clear(): void {
{
this._tilemap = []; this._tilemap = [];
this._doorLocation = { x: -1, y: -1 }; this._doorLocation = { x: -1, y: -1 }; // Updated from old code (no .set method)
this._width = 0; this._width = 0;
this._height = 0; this._height = 0;
this._isPointerDown = false; this._isPointerDown = false;
this._lastUsedTile = { x: -1, y: -1 }; this._lastUsedTile = { x: -1, y: -1 }; // Updated from old code (no .set method)
this._actionSettings.clear(); this._actionSettings.clear();
this.clearCanvas(); this.clearCanvas();
} }
public clearCanvas(): void public clearCanvas(): void {
{ this._renderer.fillStyle = '#000000';
this.renderer.fillStyle = '0x000000'; this._renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height);
this.renderer.fillRect(0, 0, this._renderer.canvas.width, this._renderer.canvas.height);
} }
public get renderer(): CanvasRenderingContext2D public zoomIn(): void { // Added from old code
{ this._zoomLevel = Math.min(this._zoomLevel + 0.1, 2.0);
this.adjustCanvasSize();
this.renderTiles();
}
public zoomOut(): void { // Added from old code
this._zoomLevel = Math.max(this._zoomLevel - 0.1, 0.5);
this.adjustCanvasSize();
this.renderTiles();
}
private adjustCanvasSize(): void { // Added from old code
const baseWidth = TILE_SIZE * MAX_NUM_TILE_PER_AXIS + 20;
const baseHeight = (TILE_SIZE * MAX_NUM_TILE_PER_AXIS) / 2 + 100;
this._renderer.canvas.width = baseWidth * this._zoomLevel;
this._renderer.canvas.height = baseHeight * this._zoomLevel;
}
public get zoomLevel(): number { // Added from old code
return this._zoomLevel;
}
public get renderer(): CanvasRenderingContext2D {
return this._renderer; return this._renderer;
} }
public get tilemap(): Tile[][] public get tilemap(): Tile[][] {
{
return this._tilemap; return this._tilemap;
} }
public get doorLocation(): { x: number, y: number } public get doorLocation(): { x: number, y: number } {
{
return this._doorLocation; return this._doorLocation;
} }
public set doorLocation(value: { x: number, y: number }) public set doorLocation(value: { x: number, y: number }) {
{
this._doorLocation = value; this._doorLocation = value;
} }
public get actionSettings(): ActionSettings public get actionSettings(): ActionSettings {
{
return this._actionSettings; return this._actionSettings;
} }
public static get instance(): FloorplanEditor public static get instance(): FloorplanEditor {
{ if (!FloorplanEditor._INSTANCE) {
if(!FloorplanEditor._INSTANCE)
{
FloorplanEditor._INSTANCE = new FloorplanEditor(); FloorplanEditor._INSTANCE = new FloorplanEditor();
} }
return FloorplanEditor._INSTANCE; return FloorplanEditor._INSTANCE;
} }
} }

View File

@ -213,15 +213,5 @@ export const spritesheet = {
spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 }, spriteSourceSize: { x: 0, y: 0, w: 34, h: 17 },
sourceSize: { w: 34, h: 17 }, sourceSize: { w: 34, h: 17 },
}, },
}, }
meta: {
app: 'https://www.codeandweb.com/texturepacker',
version: '1.0',
image: 'tiles.png',
format: 'RGBA8888',
size: { w: 108, h: 190 },
scale: '1',
smartupdate:
'$TexturePacker:SmartUpdate:6d0f8373580629749f786a0b0f6c6bb9:96dff9df69bdc6938cf02f254bbe028b:accbe1e7e294ded8391337fc1c446319$',
},
}; };

View File

@ -1,8 +1,8 @@
import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer'; import { GetOccupiedTilesMessageComposer, GetRoomEntryTileMessageComposer, RoomEntryTileMessageEvent, RoomOccupiedTilesMessageEvent } from '@nitrots/nitro-renderer';
import { FC, useEffect, useRef, useState } from 'react'; import { FC, useEffect, useRef, useState } from 'react';
import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp } from 'react-icons/fa'; import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaDotCircle, FaSearchPlus, FaSearchMinus, FaUndo } from 'react-icons/fa';
import { SendMessageComposer } from '../../../api'; import { SendMessageComposer } from '../../../api';
import { Button, Column, ColumnProps, Grid } from '../../../common'; import { Base, Button, Column, ColumnProps, Flex, Grid } from '../../../common';
import { useMessageEvent } from '../../../hooks'; import { useMessageEvent } from '../../../hooks';
import { useFloorplanEditorContext } from '../FloorplanEditorContext'; import { useFloorplanEditorContext } from '../FloorplanEditorContext';
import { FloorplanEditor } from '../common/FloorplanEditor'; import { FloorplanEditor } from '../common/FloorplanEditor';
@ -10,7 +10,7 @@ import { FloorplanEditor } from '../common/FloorplanEditor';
export const FloorplanCanvasView: FC<ColumnProps> = props => export const FloorplanCanvasView: FC<ColumnProps> = props =>
{ {
const { gap = 1, children = null, ...rest } = props; const { gap = 1, children = null, ...rest } = props;
const [ occupiedTilesReceived, setOccupiedTilesReceived ] = useState(false); const [ occupiedTilesReceived , setOccupiedTilesReceived ] = useState(false);
const [ entryTileReceived, setEntryTileReceived ] = useState(false); const [ entryTileReceived, setEntryTileReceived ] = useState(false);
const { originalFloorplanSettings = null, setOriginalFloorplanSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext(); const { originalFloorplanSettings = null, setOriginalFloorplanSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext();
const elementRef = useRef<HTMLDivElement>(null); const elementRef = useRef<HTMLDivElement>(null);
@ -58,7 +58,7 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
return newValue; return newValue;
}); });
FloorplanEditor.instance.doorLocation = { x: parser.x, y: parser.y }; FloorplanEditor.instance.doorLocation = ( parser.x, parser.y );
setEntryTileReceived(true); setEntryTileReceived(true);
}); });
@ -84,7 +84,7 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
element.scrollBy({ left: 10 }); element.scrollBy({ left: 10 });
break; break;
} }
}; }
const onPointerEvent = (event: PointerEvent) => const onPointerEvent = (event: PointerEvent) =>
{ {
@ -103,6 +103,20 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
FloorplanEditor.instance.onPointerMove(event); FloorplanEditor.instance.onPointerMove(event);
break; break;
} }
}
const handleZoomIn = () => {
FloorplanEditor.instance.zoomIn();
};
const handleZoomOut = () => {
FloorplanEditor.instance.zoomOut();
};
const handleResetZoom = () => {
FloorplanEditor.instance._zoomLevel = 1.0; // Reset to default zoom
FloorplanEditor.instance.adjustCanvasSize();
FloorplanEditor.instance.renderTiles();
}; };
useEffect(() => useEffect(() =>
@ -118,9 +132,9 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
thicknessWall: originalFloorplanSettings.thicknessWall, thicknessWall: originalFloorplanSettings.thicknessWall,
thicknessFloor: originalFloorplanSettings.thicknessFloor, thicknessFloor: originalFloorplanSettings.thicknessFloor,
entryPointDir: prevValue.entryPointDir entryPointDir: prevValue.entryPointDir
}; }
}); });
}; }
}, [ originalFloorplanSettings.thicknessFloor, originalFloorplanSettings.thicknessWall, originalFloorplanSettings.wallHeight, setVisualizationSettings ]); }, [ originalFloorplanSettings.thicknessFloor, originalFloorplanSettings.thicknessWall, originalFloorplanSettings.wallHeight, setVisualizationSettings ]);
useEffect(() => useEffect(() =>
@ -161,39 +175,30 @@ export const FloorplanCanvasView: FC<ColumnProps> = props =>
currentElement.removeEventListener('pointermove', onPointerEvent); currentElement.removeEventListener('pointermove', onPointerEvent);
} }
}; }
}, []); }, []);
const isSmallScreen = () => window.innerWidth < 768; const isSmallScreen = () => window.innerWidth < 768;
return ( return (
<Column gap={ gap } { ...rest }> <Column gap={ gap } { ...rest }>
<Grid gap={ 1 } overflow="hidden"> <Grid overflow="hidden" gap={ 1 }>
<Column center className="hidden" size={ 1 }> <Column overflow="hidden" size={ isSmallScreen() ? 10 : 12 } gap={ 1 }>
<Button className="hidden" onClick={ event => onClickArrowButton('left') }> <Flex justifyContent="left" gap={ 1 }>
<FaArrowLeft className="fa-icon" /> <Button shrink onClick={ handleZoomIn }>
</Button> <FaSearchPlus className="fa-icon" />
</Column>
<Column gap={ 1 } overflow="hidden" size={ isSmallScreen() ? 10 : 12 }>
<div className="flex hidden justify-content-enter" >
<Button shrink onClick={ event => onClickArrowButton('up') }>
<FaArrowUp className="fa-icon" />
</Button> </Button>
</div> <Button shrink onClick={ handleResetZoom }>
<div ref={ elementRef } className="overflow-auto" /> <FaDotCircle className="fa-icon" />
<div className="flex hidden justify-center">
<Button shrink onClick={ event => onClickArrowButton('down') }>
<FaArrowDown className="fa-icon" />
</Button> </Button>
</div> <Button shrink onClick={ handleZoomOut }>
</Column> <FaSearchMinus className="fa-icon" />
<Column center className="hidden" size={ 1 }> </Button>
<Button className="hidden" onClick={ event => onClickArrowButton('right') }> </Flex>
<FaArrowRight className="fa-icon" /> <Base overflow="auto" innerRef={ elementRef } />
</Button>
</Column> </Column>
</Grid> </Grid>
{ children } { children }
</Column> </Column>
); );
}; }

View File

@ -13,177 +13,172 @@ const MAX_WALL_HEIGHT: number = 16;
const MIN_FLOOR_HEIGHT: number = 0; const MIN_FLOOR_HEIGHT: number = 0;
const MAX_FLOOR_HEIGHT: number = 26; const MAX_FLOOR_HEIGHT: number = 26;
export const FloorplanOptionsView: FC<{}> = props => export const FloorplanOptionsView: FC<{}> = props => {
{ const { visualizationSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext();
const { visualizationSettings = null, setVisualizationSettings = null } = useFloorplanEditorContext(); const [floorAction, setFloorAction] = useState(FloorAction.SET);
const [ floorAction, setFloorAction ] = useState(FloorAction.SET); const [floorHeight, setFloorHeight] = useState(0);
const [ floorHeight, setFloorHeight ] = useState(0); const [isSquareSelectMode, setIsSquareSelectMode] = useState(false);
const selectAction = (action: number) => const selectAction = (action: number) => {
{ setFloorAction(action);
setFloorAction(action); FloorplanEditor.instance.actionSettings.currentAction = action;
};
FloorplanEditor.instance.actionSettings.currentAction = action; const toggleSquareSelectMode = () => {
}; setIsSquareSelectMode(prev => {
const newValue = !prev;
FloorplanEditor.instance.setSquareSelectMode(newValue);
return newValue;
});
};
const changeDoorDirection = () => const changeDoorDirection = () => {
{ setVisualizationSettings(prevValue => {
setVisualizationSettings(prevValue => const newValue = { ...prevValue };
{ newValue.entryPointDir = newValue.entryPointDir < 7 ? newValue.entryPointDir + 1 : 0;
const newValue = { ...prevValue }; return newValue;
});
};
if(newValue.entryPointDir < 7) const onFloorHeightChange = (value: number) => {
{ if (isNaN(value) || value <= 0) value = 0;
++newValue.entryPointDir; if (value > MAX_FLOOR_HEIGHT) value = MAX_FLOOR_HEIGHT;
} setFloorHeight(value);
else FloorplanEditor.instance.actionSettings.currentHeight = value.toString(36);
{ };
newValue.entryPointDir = 0;
}
return newValue; const onFloorThicknessChange = (value: number) => {
}); setVisualizationSettings(prevValue => ({
}; ...prevValue,
thicknessFloor: value,
}));
};
const onFloorHeightChange = (value: number) => const onWallThicknessChange = (value: number) => {
{ setVisualizationSettings(prevValue => ({
if(isNaN(value) || (value <= 0)) value = 0; ...prevValue,
thicknessWall: value,
}));
};
if(value > 26) value = 26; const onWallHeightChange = (value: number) => {
if (isNaN(value) || value <= 0) value = MIN_WALL_HEIGHT;
if (value > MAX_WALL_HEIGHT) value = MAX_WALL_HEIGHT;
setVisualizationSettings(prevValue => ({
...prevValue,
wallHeight: value,
}));
};
setFloorHeight(value); const increaseWallHeight = () => {
onWallHeightChange(Math.min(visualizationSettings.wallHeight + 1, MAX_WALL_HEIGHT));
};
FloorplanEditor.instance.actionSettings.currentHeight = value.toString(36); const decreaseWallHeight = () => {
}; onWallHeightChange(Math.max(visualizationSettings.wallHeight - 1, MIN_WALL_HEIGHT));
};
const onFloorThicknessChange = (value: number) => return (
{ <div className="flex flex-col">
setVisualizationSettings(prevValue => <Grid>
{ <Column gap={1} size={5}>
const newValue = { ...prevValue }; <Text bold>{LocalizeText('floor.plan.editor.draw.mode')}</Text>
<Flex gap={3}>
newValue.thicknessFloor = value; <div className="flex gap-1">
<LayoutGridItem itemActive={floorAction === FloorAction.SET} onClick={() => selectAction(FloorAction.SET)}>
return newValue; <i className="nitro-icon icon-set-tile" />
}); </LayoutGridItem>
}; <LayoutGridItem itemActive={floorAction === FloorAction.UNSET} onClick={() => selectAction(FloorAction.UNSET)}>
<i className="nitro-icon icon-unset-tile" />
const onWallThicknessChange = (value: number) => </LayoutGridItem>
{ </div>
setVisualizationSettings(prevValue => <div className="flex gap-1">
{ <LayoutGridItem itemActive={floorAction === FloorAction.UP} onClick={() => selectAction(FloorAction.UP)}>
const newValue = { ...prevValue }; <i className="nitro-icon icon-increase-height" />
</LayoutGridItem>
newValue.thicknessWall = value; <LayoutGridItem itemActive={floorAction === FloorAction.DOWN} onClick={() => selectAction(FloorAction.DOWN)}>
<i className="nitro-icon icon-decrease-height" />
return newValue; </LayoutGridItem>
}); <LayoutGridItem itemActive={floorAction === FloorAction.DOOR} onClick={() => selectAction(FloorAction.DOOR)}>
}; <i className="nitro-icon icon-set-door" />
</LayoutGridItem>
const onWallHeightChange = (value: number) => <LayoutGridItem onClick={() => FloorplanEditor.instance.toggleSelectAll()}>
{ <i className={`nitro-icon ${floorAction === FloorAction.UNSET ? 'icon-set-deselect' : 'icon-set-select'}`} />
if(isNaN(value) || (value <= 0)) value = MIN_WALL_HEIGHT; </LayoutGridItem>
<LayoutGridItem itemActive={isSquareSelectMode} onClick={toggleSquareSelectMode}>
if(value > MAX_WALL_HEIGHT) value = MAX_WALL_HEIGHT; <i className={`nitro-icon ${isSquareSelectMode ? 'icon-set-active-squaresselect' : 'icon-set-squaresselect'}`} />
</LayoutGridItem>
setVisualizationSettings(prevValue => </div>
{ </Flex>
const newValue = { ...prevValue }; </Column>
<Column alignItems="center" size={4}>
newValue.wallHeight = value; <Text bold>{LocalizeText('floor.plan.editor.enter.direction')}</Text>
<i
return newValue; className={`nitro-icon icon-door-direction-${visualizationSettings.entryPointDir} cursor-pointer`}
}); onClick={changeDoorDirection}
}; />
</Column>
const increaseWallHeight = () => <Column size={3}>
{ <Text bold>{LocalizeText('floor.editor.wall.height')}</Text>
let height = (visualizationSettings.wallHeight + 1); <div className="flex items-center gap-1">
<FaCaretLeft className="cursor-pointer fa-icon" onClick={decreaseWallHeight} />
if(height > MAX_WALL_HEIGHT) height = MAX_WALL_HEIGHT; <input
className="min-h-[calc(1.5em+.5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm quantity-input"
onWallHeightChange(height); type="number"
}; value={visualizationSettings.wallHeight}
onChange={event => onWallHeightChange(event.target.valueAsNumber)}
const decreaseWallHeight = () => />
{ <FaCaretRight className="cursor-pointer fa-icon" onClick={increaseWallHeight} />
let height = (visualizationSettings.wallHeight - 1); </div>
</Column>
if(height <= 0) height = MIN_WALL_HEIGHT; </Grid>
<Grid>
onWallHeightChange(height); <Column size={6}>
}; <Text bold>{LocalizeText('floor.plan.editor.tile.height')}: {floorHeight}</Text>
<ReactSlider
return ( className="nitro-slider"
<div className="flex flex-col"> max={MAX_FLOOR_HEIGHT}
<Grid> min={MIN_FLOOR_HEIGHT}
<Column gap={ 1 } size={ 5 }> renderThumb={({ key, style, ...rest }, state) => (
<Text bold>{ LocalizeText('floor.plan.editor.draw.mode') }</Text> <div
<Flex gap={ 3 }> key={key} // Explicitly pass key directly
<div className="flex gap-1"> style={{ backgroundColor: `#${COLORMAP[state.valueNow.toString(33)]}`, ...style }}
<LayoutGridItem itemActive={ (floorAction === FloorAction.SET) } onClick={ event => selectAction(FloorAction.SET) }> {...rest}
<i className="nitro-icon icon-set-tile" /> >
</LayoutGridItem> {state.valueNow}
<LayoutGridItem itemActive={ (floorAction === FloorAction.UNSET) } onClick={ event => selectAction(FloorAction.UNSET) }> </div>
<i className="nitro-icon icon-unset-tile" /> )}
</LayoutGridItem> step={1}
</div> value={floorHeight}
<div className="flex gap-1"> onChange={value => onFloorHeightChange(value)}
<LayoutGridItem itemActive={ (floorAction === FloorAction.UP) } onClick={ event => selectAction(FloorAction.UP) }> />
<i className="nitro-icon icon-increase-height" /> </Column>
</LayoutGridItem> <Column size={6}>
<LayoutGridItem itemActive={ (floorAction === FloorAction.DOWN) } onClick={ event => selectAction(FloorAction.DOWN) }> <Text bold>{LocalizeText('floor.plan.editor.room.options')}</Text>
<i className="nitro-icon icon-decrease-height" /> <Flex className="items-center">
</LayoutGridItem> <select
</div> className="min-h-[calc(1.5em+.5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm"
<LayoutGridItem itemActive={ (floorAction === FloorAction.DOOR) } onClick={ event => selectAction(FloorAction.DOOR) }> value={visualizationSettings.thicknessWall}
<i className="nitro-icon icon-set-door" /> onChange={event => onWallThicknessChange(parseInt(event.target.value))}
</LayoutGridItem> >
</Flex> <option value={0}>{LocalizeText('navigator.roomsettings.wall_thickness.thinnest')}</option>
</Column> <option value={1}>{LocalizeText('navigator.roomsettings.wall_thickness.thin')}</option>
<Column alignItems="center" size={ 4 }> <option value={2}>{LocalizeText('navigator.roomsettings.wall_thickness.normal')}</option>
<Text bold>{ LocalizeText('floor.plan.editor.enter.direction') }</Text> <option value={3}>{LocalizeText('navigator.roomsettings.wall_thickness.thick')}</option>
<i className={ `nitro-icon icon-door-direction-${ visualizationSettings.entryPointDir } cursor-pointer` } onClick={ changeDoorDirection } /> </select>
</Column> <select
<Column size={ 3 }> className="min-h-[calc(1.5em+.5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm"
<Text bold>{ LocalizeText('floor.editor.wall.height') }</Text> value={visualizationSettings.thicknessFloor}
<div className="flex items-center gap-1"> onChange={event => onFloorThicknessChange(parseInt(event.target.value))}
<FaCaretLeft className="cursor-pointer fa-icon" onClick={ decreaseWallHeight } /> >
<input className="min-h-[calc(1.5em+ .5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm quantity-input" type="number" value={ visualizationSettings.wallHeight } onChange={ event => onWallHeightChange(event.target.valueAsNumber) } /> <option value={0}>{LocalizeText('navigator.roomsettings.floor_thickness.thinnest')}</option>
<FaCaretRight className="cursor-pointer fa-icon" onClick={ increaseWallHeight } /> <option value={1}>{LocalizeText('navigator.roomsettings.floor_thickness.thin')}</option>
</div> <option value={2}>{LocalizeText('navigator.roomsettings.floor_thickness.normal')}</option>
</Column> <option value={3}>{LocalizeText('navigator.roomsettings.floor_thickness.thick')}</option>
</Grid> </select>
<Grid> </Flex>
<Column size={ 6 }> </Column>
<Text bold>{ LocalizeText('floor.plan.editor.tile.height') }: { floorHeight }</Text> </Grid>
<ReactSlider </div>
className="nitro-slider" );
max={ MAX_FLOOR_HEIGHT }
min={ MIN_FLOOR_HEIGHT }
renderThumb={ ({ style, ...rest }, state) => <div style={ { backgroundColor: `#${ COLORMAP[state.valueNow.toString(33)] }`, ...style } } { ...rest }>{ state.valueNow }</div> }
step={ 1 }
value={ floorHeight }
onChange={ event => onFloorHeightChange(event) } />
</Column>
<Column size={ 6 }>
<Text bold>{ LocalizeText('floor.plan.editor.room.options') }</Text>
<Flex className="items-center">
<select className="min-h-[calc(1.5em+ .5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm" value={ visualizationSettings.thicknessWall } onChange={ event => onWallThicknessChange(parseInt(event.target.value)) }>
<option value={ 0 }>{ LocalizeText('navigator.roomsettings.wall_thickness.thinnest') }</option>
<option value={ 1 }>{ LocalizeText('navigator.roomsettings.wall_thickness.thin') }</option>
<option value={ 2 }>{ LocalizeText('navigator.roomsettings.wall_thickness.normal') }</option>
<option value={ 3 }>{ LocalizeText('navigator.roomsettings.wall_thickness.thick') }</option>
</select>
<select className="min-h-[calc(1.5em+ .5rem+2px)] px-[.5rem] py-[.25rem] rounded-[.2rem] form-control-sm" value={ visualizationSettings.thicknessFloor } onChange={ event => onFloorThicknessChange(parseInt(event.target.value)) }>
<option value={ 0 }>{ LocalizeText('navigator.roomsettings.floor_thickness.thinnest') }</option>
<option value={ 1 }>{ LocalizeText('navigator.roomsettings.floor_thickness.thin') }</option>
<option value={ 2 }>{ LocalizeText('navigator.roomsettings.floor_thickness.normal') }</option>
<option value={ 3 }>{ LocalizeText('navigator.roomsettings.floor_thickness.thick') }</option>
</select>
</Flex>
</Column>
</Grid>
</div>
);
}; };

View File

@ -0,0 +1,9 @@
.nitro-floorplan-editor {
width: 760px;
height: 500px;
}
.floorplan-import-export {
width: 630px;
height: 475px;
}

659
src/css/icons/icons.css Normal file
View File

@ -0,0 +1,659 @@
.nitro-icon {
display: inline-block;
background: transparent;
background-position: center;
background-repeat: no-repeat;
outline: 0;
}
.nitro-icon:hover {
transform: translate(-1px, -1px);
filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.5));
}
.nitro-icon:active {
transform: none;
filter: none;
}
.nitro-icon.icon-nitro-light {
background-image: url("@/assets/images/nitro/nitro-n-light.svg");
}
.nitro-icon.icon-nitro-dark {
background-image: url("@/assets/images/nitro/nitro-n-dark.svg");
}
.nitro-icon.icon-nitro-light,
.nitro-icon.icon-nitro-dark {
width: 100%;
height: 40px;
}
.nitro-icon.icon-catalog {
background-image: url("@/assets/images/toolbar/icons/catalog.png");
width: 37px;
height: 36px;
}
.nitro-icon.icon-game {
background-image: url("@/assets/images/toolbar/icons/game.png");
width: 44px;
height: 25px;
}
.nitro-icon.icon-rooms {
background-image: url("@/assets/images/toolbar/icons/rooms.png");
width: 44px;
height: 30px;
}
.nitro-icon.icon-house {
background-image: url("@/assets/images/toolbar/icons/house.png");
width: 32px;
height: 30px;
}
.nitro-icon.gray {
opacity: 0.5;
}
.nitro-icon.icon-inventory {
background-image: url("@/assets/images/toolbar/icons/inventory.png");
width: 44px;
height: 41px;
}
.nitro-icon.icon-modtools {
background-image: url("@/assets/images/toolbar/icons/modtools.png");
width: 29px;
height: 34px;
}
.nitro-icon.icon-friendall {
background-image: url("@/assets/images/toolbar/icons/friend_all.png");
width: 32px;
height: 33px;
}
.nitro-icon.icon-friendsearch {
background-image: url("@/assets/images/toolbar/icons/friend_search.png");
width: 29px;
height: 33px;
}
.nitro-icon.icon-sendmessage {
background-image: url("@/assets/images/toolbar/icons/sendmessage.png");
width: 20px;
height: 21px;
}
.nitro-icon.icon-me-talents {
background-image: url("@/assets/images/toolbar/icons/me-menu/talents.png");
width: 32px;
height: 30px;
}
.nitro-icon.icon-me-helper-tool {
background-image: url("@/assets/images/toolbar/icons/me-menu/helper-tool.png");
width: 32px;
height: 30px;
}
.nitro-icon.icon-me-profile {
background-image: url("@/assets/images/toolbar/icons/me-menu/profile.png");
width: 32px;
height: 30px;
}
.nitro-icon.icon-me-forums {
background-image: url("@/assets/images/toolbar/icons/me-menu/forums.png");
width: 32px;
height: 30px;
}
.nitro-icon.icon-me-rooms {
background-image: url("@/assets/images/toolbar/icons/me-menu/my-rooms.png");
width: 30px;
height: 30px;
}
.nitro-icon.icon-me-achievements {
background-image: url("@/assets/images/toolbar/icons/me-menu/achievements.png");
width: 31px;
height: 30px;
}
.nitro-icon.icon-me-clothing {
background-image: url("@/assets/images/toolbar/icons/me-menu/clothing.png");
width: 27px;
height: 30px;
}
.nitro-icon.icon-me-settings {
background-image: url("@/assets/images/toolbar/icons/me-menu/cog.png");
width: 28px;
height: 34px;
}
.nitro-icon.icon-cog {
background: url("@/assets/images/icons/icon_cog.png");
width: 14px;
height: 15px;
}
.nitro-icon.icon-help {
background: url("@/assets/images/icons/help.png");
width: 13px;
height: 23px;
}
.nitro-icon.icon-joinroom {
background-image: url("@/assets/images/toolbar/icons/joinroom.png");
width: 21px;
height: 21px;
}
.nitro-icon.icon-habbo {
background-image: url("@/assets/images/toolbar/icons/habbo.png");
width: 28px;
height: 28px;
}
.nitro-icon.icon-camera {
background-image: url("@/assets/images/toolbar/icons/camera.png");
width: 38px;
height: 45px;
}
.nitro-icon.icon-message {
background-image: url("@/assets/images/toolbar/icons/message.png");
width: 36px;
height: 32px;
}
.nitro-icon.icon-message.is-unseen {
background-image: url("@/assets/images/toolbar/icons/message_unsee.gif");
}
.nitro-icon.icon-wired-trigger {
background-image: url("@/assets/images/wired/icon_trigger.png");
width: 13px;
height: 14px;
}
.nitro-icon.icon-wired-condition {
background-image: url("@/assets/images/wired/icon_condition.png");
width: 13px;
height: 14px;
}
.nitro-icon.icon-wired-action {
background-image: url("@/assets/images/wired/icon_action.png");
width: 13px;
height: 14px;
}
.nitro-icon.chatstyles-icon {
background-image: url("@/assets/images/chat/styles-icon.png");
width: 17px;
height: 19px;
filter: grayscale(100%);
}
.nitro-icon.chatstyles-icon:hover {
filter: grayscale(0%);
}
.nitro-icon.pencil-icon {
background-image: url("@/assets/images/infostand/pencil-icon.png");
width: 17px;
height: 18px;
}
.nitro-icon.disk-icon {
background-image: url("@/assets/images/infostand/disk-icon.png");
width: 14px;
height: 14px;
}
.nitro-icon.disk-creator {
background-image: url("@/assets/images/infostand/disk-creator.png");
width: 14px;
height: 14px;
}
.nitro-icon.trade-locked-icon {
background-image: url("@/assets/images/inventory/trading/locked-icon.png");
width: 29px;
height: 43px;
}
.nitro-icon.trade-unlocked-icon {
background-image: url("@/assets/images/inventory/trading/unlocked-icon.png");
width: 29px;
height: 43px;
}
.nitro-icon.modtool-room-icon {
background-image: url("@/assets/images/modtool/room.png");
width: 20px;
height: 15px;
}
.nitro-icon.modtool-chatlog-icon {
background-image: url("@/assets/images/modtool/chatlog.gif");
width: 20px;
height: 15px;
}
.nitro-icon.modtool-user-icon {
background-image: url("@/assets/images/modtool/user.gif");
width: 20px;
height: 15px;
}
.nitro-icon.modtool-reports-icon {
background-image: url("@/assets/images/modtool/reports.png");
width: 20px;
height: 15px;
}
.nitro-icon.modtool-wrench-icon {
background-image: url("@/assets/images/modtool/wrench.gif");
width: 20px;
height: 15px;
}
.nitro-icon.modtool-key-icon {
background-image: url("@/assets/images/modtool/key.gif");
width: 20px;
height: 15px;
}
.nitro-icon.icon-catalogue-hc_small {
background-image: url("@/assets/images/catalog/hc_small.png");
width: 31px;
height: 17px;
}
.nitro-icon.icon-catalogue-hc_big {
background: url("@/assets/images/catalog/hc_big.png");
width: 68px;
height: 40px;
}
.nitro-icon.icon-sign-exclamation {
background: url("@/assets/images/icons/sign-exclamation.png");
width: 7px;
height: 17px;
}
.nitro-icon.icon-sign-heart {
background: url("@/assets/images/icons/sign-heart.png");
width: 15px;
height: 13px;
}
.nitro-icon.icon-sign-red {
background: url("@/assets/images/icons/sign-red.png");
width: 11px;
height: 19px;
}
.nitro-icon.icon-sign-yellow {
background: url("@/assets/images/icons/sign-yellow.png");
width: 11px;
height: 19px;
}
.nitro-icon.icon-sign-skull {
background: url("@/assets/images/icons/sign-skull.png");
width: 12px;
height: 12px;
}
.nitro-icon.icon-sign-smile {
background: url("@/assets/images/icons/sign-smile.png");
width: 7px;
height: 14px;
}
.nitro-icon.icon-sign-soccer {
background: url("@/assets/images/icons/sign-soccer.png");
width: 20px;
height: 20px;
}
.nitro-icon.icon-house-small {
background: url("@/assets/images/icons/house-small.png");
width: 19px;
height: 14px;
}
.nitro-icon.icon-camera-small {
background: url("@/assets/images/icons/camera-small.png");
width: 17px;
height: 15px;
}
.nitro-icon.icon-small-room {
background: url("@/assets/images/icons/small-room.png");
width: 17px;
height: 16px;
}
.nitro-icon.icon-cog {
background: url("@/assets/images/icons/cog.png");
width: 21px;
height: 21px;
}
.nitro-icon.icon-chat-history {
background: url("@/assets/images/icons/chat-history.png");
width: 17px;
height: 21px;
}
.nitro-icon.icon-room-link {
background: url("@/assets/images/icons/room-link.png");
width: 17px;
height: 15px;
}
.nitro-icon.icon-zoom-more {
background: url("@/assets/images/icons/zoom-more.png");
width: 12px;
height: 22px;
}
.nitro-icon.icon-zoom-less {
background: url("@/assets/images/icons/zoom-less.png");
width: 12px;
height: 22px;
}
.nitro-icon.icon-like-room {
background: url("@/assets/images/icons/like-room.png");
width: 20px;
height: 22px;
}
.nitro-icon.icon-arrows {
background: url("@/assets/images/icons/arrows.png");
width: 17px;
height: 15px;
}
.nitro-icon.icon-camera-colormatrix {
background: url("@/assets/images/icons/camera-colormatrix.png");
width: 32px;
height: 21px;
}
.nitro-icon.icon-camera-composite {
background: url("@/assets/images/icons/camera-composite.png");
width: 32px;
height: 21px;
}
.nitro-icon.icon-pf-online {
background: url("@/assets/images/profile/icons/online.gif");
width: 40px;
height: 16px;
}
.nitro-icon.icon-pf-offline {
background: url("@/assets/images/profile/icons/offline.png");
width: 39px;
height: 16px;
}
.nitro-icon.icon-pf-tick {
background: url("@/assets/images/profile/icons/tick.png");
width: 11px;
height: 10px;
}
.nitro-icon.icon-group-type-0 {
background: url("@/assets/images/groups/icons/grouptype_icon_0.png");
width: 16px;
height: 16px;
}
.nitro-icon.icon-group-type-1 {
background: url("@/assets/images/groups/icons/grouptype_icon_1.png");
width: 16px;
height: 16px;
}
.nitro-icon.icon-group-type-2 {
background: url("@/assets/images/groups/icons/grouptype_icon_2.png");
width: 16px;
height: 16px;
}
.nitro-icon.icon-group-decorate {
background: url("@/assets/images/groups/icons/group_decorate_icon.png");
width: 15px;
height: 15px;
}
.nitro-icon.icon-group-member {
background: url("@/assets/images/groups/icons/group_icon_big_member.png");
width: 20px;
height: 20px;
}
.nitro-icon.icon-group-admin {
background: url("@/assets/images/groups/icons/group_icon_big_admin.png");
width: 20px;
height: 20px;
}
.nitro-icon.icon-group-owner {
background: url("@/assets/images/groups/icons/group_icon_big_owner.png");
width: 20px;
height: 20px;
}
.nitro-icon.icon-group-favorite {
background: url("@/assets/images/groups/icons/group_favorite.png");
width: 14px;
height: 14px;
}
.nitro-icon.icon-group-not-favorite {
background: url("@/assets/images/groups/icons/group_notfavorite.png");
width: 14px;
height: 14px;
}
.nitro-icon.icon-group-small-admin {
background: url("@/assets/images/groups/icons/group_icon_admin.png");
width: 11px;
height: 13px;
}
.nitro-icon.icon-group-small-not-admin {
background: url("@/assets/images/groups/icons/group_icon_not_admin.png");
width: 11px;
height: 13px;
}
.nitro-icon.icon-group-small-owner {
background: url("@/assets/images/groups/icons/group_icon_small_owner.png");
width: 13px;
height: 13px;
}
.nitro-icon.icon-navigator-info {
background: url("@/assets/images/navigator/icons/info.png");
width: 18px;
height: 18px;
}
.nitro-icon.icon-navigator-room-locked {
background: url("@/assets/images/navigator/icons/room_locked.png");
width: 13px;
height: 16px;
}
.nitro-icon.icon-navigator-room-password {
background: url("@/assets/images/navigator/icons/room_password.png");
width: 13px;
height: 16px;
}
.nitro-icon.icon-navigator-room-invisible {
background: url("@/assets/images/navigator/icons/room_invisible.png");
width: 13px;
height: 16px;
}
.nitro-icon.icon-navigator-room-group {
background: url("@/assets/images/navigator/icons/room_group.png");
width: 13px;
height: 11px;
}
.nitro-icon.icon-youtube-next {
background: url("@/assets/images/room-widgets/youtube-widget/next.png");
width: 21px;
height: 16px;
}
.nitro-icon.icon-youtube-prev {
background: url("@/assets/images/room-widgets/youtube-widget/prev.png");
width: 21px;
height: 16px;
}
.nitro-icon.icon-hc-banner {
background: url("@/assets/images/catalog/hc_big.png");
width: 68px;
height: 40px;
}
.nitro-icon.icon-set-tile {
background-image: url("@/assets/images/floorplaneditor/icon-tile-set.png");
width: 40px;
height: 40px;
}
.nitro-icon.icon-unset-tile {
background-image: url("@/assets/images/floorplaneditor/icon-tile-unset.png");
width: 40px;
height: 40px;
}
.nitro-icon.icon-increase-height {
background-image: url("@/assets/images/floorplaneditor/icon-tile-up.png");
width: 40px;
height: 40px;
}
.nitro-icon.icon-decrease-height {
background-image: url("@/assets/images/floorplaneditor/icon-tile-down.png");
width: 40px;
height: 40px;
}
.nitro-icon.icon-set-door {
background-image: url("@/assets/images/floorplaneditor/icon-door.png");
width: 40px;
height: 40px;
}
.nitro-icon.icon-door-direction-0 {
background-image: url("@/assets/images/floorplaneditor/door-direction-0.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-1 {
background-image: url("@/assets/images/floorplaneditor/door-direction-1.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-2 {
background-image: url("@/assets/images/floorplaneditor/door-direction-2.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-3 {
background-image: url("@/assets/images/floorplaneditor/door-direction-3.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-4 {
background-image: url("@/assets/images/floorplaneditor/door-direction-4.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-5 {
background-image: url("@/assets/images/floorplaneditor/door-direction-5.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-6 {
background-image: url("@/assets/images/floorplaneditor/door-direction-6.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-door-direction-7 {
background-image: url("@/assets/images/floorplaneditor/door-direction-7.png");
width: 80px;
height: 45px;
}
.nitro-icon.icon-set-select {
background-image: url('@/assets/images/floorplaneditor/icon-select.png');
width: 40px;
height: 40px;
}
.nitro-icon.icon-set-deselect {
background-image: url('@/assets/images/floorplaneditor/icon-deselect.png');
width: 40px;
height: 40px;
}
.nitro-icon.icon-set-squaresselect {
background-image: url('@/assets/images/floorplaneditor/icon-squaresselect.png');
width: 40px;
height: 40px;
}
.nitro-icon.icon-set-active-squaresselect {
background-image: url('@/assets/images/floorplaneditor/icon-squaresselect.png');
width: 40px;
height: 40px;
}
.nitro-icon.icon-tickets {
background-image: url("@/assets/images/icons/tickets.png");
width: 17px;
height: 17px;
}
.nitro-icon.icon-user {
background-image: url("@/assets/images/icons/user.png");
width: 18px;
height: 19px;
}
.nitro-icon.icon-loading {
background-image: url("@/assets/images/ui/loading_icon.png");
}
.nitro-icon.icon-loading.with-size {
width: 16px;
height: 16px;
}

View File

@ -190,636 +190,6 @@ body {
@apply bg-[-19px]; @apply bg-[-19px];
} }
} }
.nitro-icon {
@apply inline-block bg-transparent bg-center bg-no-repeat outline-0;
&:hover {
@apply translate-x-[-1px] translate-y-[-1px] drop-shadow-hover
}
&:active {
@apply transform-none filter-none
}
&.icon-nitro-light {
background-image: url("@/assets/images/nitro/nitro-n-light.svg");
}
&.icon-nitro-dark {
background-image: url("@/assets/images/nitro/nitro-n-dark.svg");
}
&.icon-nitro-light,
&.icon-nitro-dark {
width: 100%;
height: 40px;
}
&.icon-catalog {
background-image: url("@/assets/images/toolbar/icons/catalog.png");
width: 37px;
height: 36px;
}
&.icon-game {
background-image: url("@/assets/images/toolbar/icons/game.png");
width: 44px;
height: 25px;
}
&.icon-rooms {
background-image: url("@/assets/images/toolbar/icons/rooms.png");
width: 44px;
height: 30px;
}
&.icon-house {
background-image: url("@/assets/images/toolbar/icons/house.png");
height: 30px;
width: 32px;
}
&.gray {
opacity: 0.5;
}
&.icon-inventory {
background-image: url("@/assets/images/toolbar/icons/inventory.png");
height: 41px;
width: 44px;
}
&.icon-modtools {
background-image: url("@/assets/images/toolbar/icons/modtools.png");
height: 34px;
width: 29px;
}
&.icon-friendall {
background-image: url("@/assets/images/toolbar/icons/friend_all.png");
height: 33px;
width: 32px;
}
&.icon-friendsearch {
background-image: url("@/assets/images/toolbar/icons/friend_search.png");
height: 33px;
width: 29px;
}
&.icon-sendmessage {
background-image: url("@/assets/images/toolbar/icons/sendmessage.png");
width: 20px;
height: 21px;
}
&.icon-me-talents {
background-image: url("@/assets/images/toolbar/icons/me-menu/talents.png");
width: 32px;
height: 30px;
}
&.icon-me-helper-tool {
background-image: url("@/assets/images/toolbar/icons/me-menu/helper-tool.png");
width: 32px;
height: 30px;
}
&.icon-me-profile {
background-image: url("@/assets/images/toolbar/icons/me-menu/profile.png");
width: 32px;
height: 30px;
}
&.icon-me-forums {
background-image: url("@/assets/images/toolbar/icons/me-menu/forums.png");
width: 32px;
height: 30px;
}
&.icon-me-rooms {
background-image: url("@/assets/images/toolbar/icons/me-menu/my-rooms.png");
width: 30px;
height: 30px;
}
&.icon-me-achievements {
background-image: url("@/assets/images/toolbar/icons/me-menu/achievements.png");
width: 31px;
height: 30px;
}
&.icon-me-clothing {
background-image: url("@/assets/images/toolbar/icons/me-menu/clothing.png");
width: 27px;
height: 30px;
}
&.icon-me-settings {
background-image: url("@/assets/images/toolbar/icons/me-menu/cog.png");
width: 28px;
height: 34px;
}
&.icon-cog {
background: url("@/assets/images/icons/icon_cog.png");
width: 14px;
height: 15px;
}
&.icon-help {
background: url("@/assets/images/icons/help.png");
width: 13px;
height: 23px;
}
&.icon-joinroom {
background-image: url("@/assets/images/toolbar/icons/joinroom.png");
width: 21px;
height: 21px;
}
&.icon-habbo {
background-image: url("@/assets/images/toolbar/icons/habbo.png");
width: 28px;
height: 28px;
}
&.icon-camera {
background-image: url("@/assets/images/toolbar/icons/camera.png");
width: 38px;
height: 45px;
}
&.icon-message {
background-image: url("@/assets/images/toolbar/icons/message.png");
width: 36px;
height: 32px;
&.is-unseen {
background-image: url("@/assets/images/toolbar/icons/message_unsee.gif");
}
}
&.icon-wired-trigger {
background-image: url("@/assets/images/wired/icon_trigger.png");
width: 13px;
height: 14px;
}
&.icon-wired-condition {
background-image: url("@/assets/images/wired/icon_condition.png");
width: 13px;
height: 14px;
}
&.icon-wired-action {
background-image: url("@/assets/images/wired/icon_action.png");
width: 13px;
height: 14px;
}
&.chatstyles-icon {
background-image: url("@/assets/images/chat/styles-icon.png");
width: 17px;
height: 19px;
filter: grayscale(100%);
&:hover {
filter: grayscale(0%);
}
}
&.pencil-icon {
background-image: url("@/assets/images/infostand/pencil-icon.png");
width: 17px;
height: 18px;
}
&.disk-icon {
background-image: url("@/assets/images/infostand/disk-icon.png");
width: 14px;
height: 14px;
}
&.disk-creator {
background-image: url("@/assets/images/infostand/disk-creator.png");
width: 14px;
height: 14px;
}
&.trade-locked-icon {
background-image: url("@/assets/images/inventory/trading/locked-icon.png");
width: 29px;
height: 43px;
}
&.trade-unlocked-icon {
background-image: url("@/assets/images/inventory/trading/unlocked-icon.png");
width: 29px;
height: 43px;
}
&.modtool-room-icon {
background-image: url("@/assets/images/modtool/room.png");
width: 20px;
height: 15px;
}
&.modtool-chatlog-icon {
background-image: url("@/assets/images/modtool/chatlog.gif");
width: 20px;
height: 15px;
}
&.modtool-user-icon {
background-image: url("@/assets/images/modtool/user.gif");
width: 20px;
height: 15px;
}
&.modtool-reports-icon {
background-image: url("@/assets/images/modtool/reports.png");
width: 20px;
height: 15px;
}
&.modtool-wrench-icon {
background-image: url("@/assets/images/modtool/wrench.gif");
width: 20px;
height: 15px;
}
&.modtool-key-icon {
background-image: url("@/assets/images/modtool/key.gif");
width: 20px;
height: 15px;
}
&.icon-catalogue-hc_small {
background-image: url("@/assets/images/catalog/hc_small.png");
height: 17px;
width: 31px;
}
&.icon-catalogue-hc_big {
background: url("@/assets/images/catalog/hc_big.png");
width: 68px;
height: 40px;
}
&.icon-sign-exclamation {
background: url("@/assets/images/icons/sign-exclamation.png");
width: 7px;
height: 17px;
}
&.icon-sign-heart {
background: url("@/assets/images/icons/sign-heart.png");
width: 15px;
height: 13px;
}
&.icon-sign-red {
background: url("@/assets/images/icons/sign-red.png");
width: 11px;
height: 19px;
}
&.icon-sign-yellow {
background: url("@/assets/images/icons/sign-yellow.png");
width: 11px;
height: 19px;
}
&.icon-sign-skull {
background: url("@/assets/images/icons/sign-skull.png");
width: 12px;
height: 12px;
}
&.icon-sign-smile {
background: url("@/assets/images/icons/sign-smile.png");
width: 7px;
height: 14px;
}
&.icon-sign-soccer {
background: url("@/assets/images/icons/sign-soccer.png");
width: 20px;
height: 20px;
}
&.icon-house-small {
background: url("@/assets/images/icons/house-small.png");
width: 19px;
height: 14px;
}
&.icon-camera-small {
background: url("@/assets/images/icons/camera-small.png");
width: 17px;
height: 15px;
}
&.icon-small-room {
background: url("@/assets/images/icons/small-room.png");
width: 17px;
height: 16px;
}
&.icon-cog {
background: url("@/assets/images/icons/cog.png");
width: 21px;
height: 21px;
}
&.icon-chat-history {
background: url("@/assets/images/icons/chat-history.png");
width: 17px;
height: 21px;
}
&.icon-room-link {
background: url("@/assets/images/icons/room-link.png");
width: 17px;
height: 15px;
}
&.icon-zoom-more {
background: url("@/assets/images/icons/zoom-more.png");
width: 12px;
height: 22px;
}
&.icon-zoom-less {
background: url("@/assets/images/icons/zoom-less.png");
width: 12px;
height: 22px;
}
&.icon-like-room {
background: url("@/assets/images/icons/like-room.png");
width: 20px;
height: 22px;
}
&.icon-arrows {
background: url("@/assets/images/icons/arrows.png");
width: 17px;
height: 15px;
}
&.icon-camera-colormatrix {
background: url("@/assets/images/icons/camera-colormatrix.png");
width: 32px;
height: 21px;
}
&.icon-camera-composite {
background: url("@/assets/images/icons/camera-composite.png");
width: 32px;
height: 21px;
}
&.icon-pf-online {
background: url("@/assets/images/profile/icons/online.gif");
width: 40px;
height: 16px;
}
&.icon-pf-offline {
background: url("@/assets/images/profile/icons/offline.png");
width: 39px;
height: 16px;
}
&.icon-pf-tick {
background: url("@/assets/images/profile/icons/tick.png");
width: 11px;
height: 10px;
}
&.icon-group-type-0 {
background: url("@/assets/images/groups/icons/grouptype_icon_0.png");
width: 16px;
height: 16px;
}
&.icon-group-type-1 {
background: url("@/assets/images/groups/icons/grouptype_icon_1.png");
width: 16px;
height: 16px;
}
&.icon-group-type-2 {
background: url("@/assets/images/groups/icons/grouptype_icon_2.png");
width: 16px;
height: 16px;
}
&.icon-group-decorate {
background: url("@/assets/images/groups/icons/group_decorate_icon.png");
width: 15px;
height: 15px;
}
&.icon-group-member {
background: url("@/assets/images/groups/icons/group_icon_big_member.png");
width: 20px;
height: 20px;
}
&.icon-group-admin {
background: url("@/assets/images/groups/icons/group_icon_big_admin.png");
width: 20px;
height: 20px;
}
&.icon-group-owner {
background: url("@/assets/images/groups/icons/group_icon_big_owner.png");
width: 20px;
height: 20px;
}
&.icon-group-favorite {
background: url("@/assets/images/groups/icons/group_favorite.png");
width: 14px;
height: 14px;
}
&.icon-group-not-favorite {
background: url("@/assets/images/groups/icons/group_notfavorite.png");
width: 14px;
height: 14px;
}
&.icon-group-small-admin {
background: url("@/assets/images/groups/icons/group_icon_admin.png");
width: 11px;
height: 13px;
}
&.icon-group-small-not-admin {
background: url("@/assets/images/groups/icons/group_icon_not_admin.png");
width: 11px;
height: 13px;
}
&.icon-group-small-owner {
background: url("@/assets/images/groups/icons/group_icon_small_owner.png");
width: 13px;
height: 13px;
}
&.icon-navigator-info {
background: url("@/assets/images/navigator/icons/info.png");
width: 18px;
height: 18px;
}
&.icon-navigator-room-locked {
background: url("@/assets/images/navigator/icons/room_locked.png");
width: 13px;
height: 16px;
}
&.icon-navigator-room-password {
background: url("@/assets/images/navigator/icons/room_password.png");
width: 13px;
height: 16px;
}
&.icon-navigator-room-invisible {
background: url("@/assets/images/navigator/icons/room_invisible.png");
width: 13px;
height: 16px;
}
&.icon-navigator-room-group {
background: url("@/assets/images/navigator/icons/room_group.png");
width: 13px;
height: 11px;
}
&.icon-youtube-next {
background: url("@/assets/images/room-widgets/youtube-widget/next.png");
width: 21px;
height: 16px;
}
&.icon-youtube-prev {
background: url("@/assets/images/room-widgets/youtube-widget/prev.png");
width: 21px;
height: 16px;
}
&.icon-hc-banner {
background: url("@/assets/images/catalog/hc_big.png");
width: 68px;
height: 40px;
}
&.icon-set-tile {
background-image: url("@/assets/images/floorplaneditor/icon-tile-set.png");
width: 40px;
height: 40px;
}
&.icon-unset-tile {
background-image: url("@/assets/images/floorplaneditor/icon-tile-unset.png");
width: 40px;
height: 40px;
}
&.icon-increase-height {
background-image: url("@/assets/images/floorplaneditor/icon-tile-up.png");
width: 40px;
height: 40px;
}
&.icon-decrease-height {
background-image: url("@/assets/images/floorplaneditor/icon-tile-down.png");
width: 40px;
height: 40px;
}
&.icon-set-door {
background-image: url("@/assets/images/floorplaneditor/icon-door.png");
width: 40px;
height: 40px;
}
&.icon-door-direction-0 {
background-image: url("@/assets/images/floorplaneditor/door-direction-0.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-1 {
background-image: url("@/assets/images/floorplaneditor/door-direction-1.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-2 {
background-image: url("@/assets/images/floorplaneditor/door-direction-2.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-3 {
background-image: url("@/assets/images/floorplaneditor/door-direction-3.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-4 {
background-image: url("@/assets/images/floorplaneditor/door-direction-4.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-5 {
background-image: url("@/assets/images/floorplaneditor/door-direction-5.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-6 {
background-image: url("@/assets/images/floorplaneditor/door-direction-6.png");
width: 80px;
height: 45px;
}
&.icon-door-direction-7 {
background-image: url("@/assets/images/floorplaneditor/door-direction-7.png");
width: 80px;
height: 45px;
}
&.icon-tickets {
background-image: url("@/assets/images/icons/tickets.png");
width: 17px;
height: 17px;
}
&.icon-user {
background-image: url("@/assets/images/icons/user.png");
width: 18px;
height: 19px;
}
&.icon-loading {
background-image: url("@/assets/images/ui/loading_icon.png");
&.with-size {
width: 16px;
height: 16px;
}
}
}
} }
.unique-item { .unique-item {
@ -916,7 +286,7 @@ body {
&.n-0 { &.n-0 {
width: 4px; width: 4px;
background-position: -1px 0px; baseackground-position: -1px 0px;
} }
&.n-1 { &.n-1 {

54
src/css/slider.css Normal file
View File

@ -0,0 +1,54 @@
.nitro-slider {
display: flex;
align-items: center;
width: 100%;
height: 25px;
.track {
height: 3px;
border-radius: $border-radius;
overflow: hidden;
&.track-0 {
background-color: $primary;
}
&.track-1 {
background-color: $muted;
}
}
.thumb {
border-radius: 50%;
width: 25px;
height: 25px;
background-color: gray;
font-size: 10px;
text-align: center;
line-height: 25px;
padding: 0 3px;
&:hover,
.active {
cursor: pointer;
}
&.active {
outline: none;
}
&.degree {
&:after {
content: '\00b0'
}
}
&.percent {
&:after {
content: '\0025'
}
}
}
}

View File

@ -134,7 +134,7 @@ const useMessengerState = () =>
{ {
const parser = event.getParser(); const parser = event.getParser();
simpleAlert(`Received room invite error: ${parser.errorCode},recipients: ${parser.failedRecipients.join(',')}`, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title')); simpleAlert(`Received room invite error: ${ parser.errorCode },recipients: ${ parser.failedRecipients.join(',') }`, NotificationAlertType.DEFAULT, null, null, LocalizeText('friendlist.alert.title'));
}); });
useEffect(() => useEffect(() =>

File diff suppressed because it is too large Load Diff

View File

@ -2,20 +2,28 @@ import { createRoot } from 'react-dom/client';
import { App } from './App'; import { App } from './App';
import './css/index.css'; import './css/index.css';
import './css/NitroCardView.css';
import './css/PurseView.css';
import './css/chat/chats.css'; import './css/chat/chats.css';
import './css/hotelview/HotelView.scss'; import './css/floorplan/FloorplanEditorView.css';
import './css/hotelview/HotelView.css';
import './css/icons/icons.css';
import './css/loading/loading.css'; import './css/loading/loading.css';
import './css/nitrocard/NitroCardView.css';
import './css/notification/NotificationCenterView.css'; import './css/notification/NotificationCenterView.css';
import './css/purse/PurseView.css';
import './css/room/ChatHistoryView.css'; import './css/room/ChatHistoryView.css';
import './css/room/RoomWidgets.css'; import './css/room/RoomWidgets.css';
import './css/slider.css';
import './css/widgets/FurnitureWidgets.css'; import './css/widgets/FurnitureWidgets.css';
createRoot(document.getElementById('root')).render(<App />); createRoot(document.getElementById('root')).render(<App />);