mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 02:59:19 +01:00
Merge branch 'feature/ocelot-card' into develop
This commit is contained in:
commit
82de79bdd1
BIN
sprites/items/OcelotCard.png
Normal file
BIN
sprites/items/OcelotCard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@ -154,4 +154,11 @@ Grid3DColor = #303030
|
|||||||
Grid3DPosX = #c9205a
|
Grid3DPosX = #c9205a
|
||||||
Grid3DNegX = #6e213b
|
Grid3DNegX = #6e213b
|
||||||
Grid3DPosZ = #255cba
|
Grid3DPosZ = #255cba
|
||||||
Grid3DNegZ = #264170
|
Grid3DNegZ = #264170
|
||||||
|
|
||||||
|
LogBackground = #222222
|
||||||
|
LogBorder = #666666
|
||||||
|
LogEntryBackground = #cccccc
|
||||||
|
LogEntryBorder = #888888
|
||||||
|
|
||||||
|
OcelotCardTooltip = #c1905f
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 116 KiB |
@ -1,275 +1,276 @@
|
|||||||
BackgroundPattern 0 0 304 304
|
BackgroundPattern 0 0 304 304
|
||||||
BarSegment 493 479 16 4
|
BarSegment 29 499 16 4
|
||||||
Empty 473 277 16 16
|
Empty 153 381 16 16
|
||||||
EmptySlot 233 379 18 18
|
EmptySlot 256 330 18 18
|
||||||
Knob 447 208 50 50
|
Knob 692 0 50 50
|
||||||
KnobCenter 233 305 50 50
|
KnobCenter 743 0 50 50
|
||||||
KnobLimits 284 305 50 50
|
KnobLimits 794 0 50 50
|
||||||
ShadowBorder 497 305 1 24
|
ShadowBorder 0 538 1 24
|
||||||
ShadowCorner 372 305 24 24
|
ShadowCorner 153 305 24 24
|
||||||
TabArrow 85 496 8 14
|
TabArrow 0 484 8 14
|
||||||
blocks/Generic 490 277 16 16
|
blocks/Generic 170 381 16 16
|
||||||
blocks/HologramEffect 277 498 4 4
|
blocks/HologramEffect 8 547 4 4
|
||||||
blocks/HologramProjector1Top 486 129 16 16
|
blocks/HologramProjector1Top 187 381 16 16
|
||||||
blocks/HologramProjector2Top 486 146 16 16
|
blocks/HologramProjector2Top 204 381 16 16
|
||||||
blocks/HologramProjectorSide 486 163 16 16
|
blocks/HologramProjectorSide 221 381 16 16
|
||||||
buttons/BottomDrawerClose 252 379 18 18
|
buttons/BottomDrawerClose 275 330 18 18
|
||||||
buttons/BottomDrawerOpen 271 379 18 18
|
buttons/BottomDrawerOpen 294 330 18 18
|
||||||
buttons/OpenFMRadioCloseOff 248 496 7 8
|
buttons/OpenFMRadioCloseOff 48 510 7 8
|
||||||
buttons/OpenFMRadioCloseOn 256 496 7 8
|
buttons/OpenFMRadioCloseOn 56 510 7 8
|
||||||
buttons/OpenFMRadioRedstoneOff 203 496 8 8
|
buttons/OpenFMRadioRedstoneOff 3 510 8 8
|
||||||
buttons/OpenFMRadioRedstoneOn 212 496 8 8
|
buttons/OpenFMRadioRedstoneOn 12 510 8 8
|
||||||
buttons/OpenFMRadioStartOff 397 305 24 24
|
buttons/OpenFMRadioStartOff 178 305 24 24
|
||||||
buttons/OpenFMRadioStartOn 422 305 24 24
|
buttons/OpenFMRadioStartOn 203 305 24 24
|
||||||
buttons/OpenFMRadioStopOff 447 305 24 24
|
buttons/OpenFMRadioStopOff 228 305 24 24
|
||||||
buttons/OpenFMRadioStopOn 472 305 24 24
|
buttons/OpenFMRadioStopOn 253 305 24 24
|
||||||
buttons/OpenFMRadioVolumeDownOff 130 496 10 10
|
buttons/OpenFMRadioVolumeDownOff 9 484 10 10
|
||||||
buttons/OpenFMRadioVolumeDownOn 141 496 10 10
|
buttons/OpenFMRadioVolumeDownOn 20 484 10 10
|
||||||
buttons/OpenFMRadioVolumeUpOff 152 496 10 10
|
buttons/OpenFMRadioVolumeUpOff 31 484 10 10
|
||||||
buttons/OpenFMRadioVolumeUpOn 163 496 10 10
|
buttons/OpenFMRadioVolumeUpOn 42 484 10 10
|
||||||
buttons/PowerOff 290 379 18 18
|
buttons/PowerOff 313 330 18 18
|
||||||
buttons/PowerOn 309 379 18 18
|
buttons/PowerOn 332 330 18 18
|
||||||
icons/Antenna 486 180 16 16
|
icons/Antenna 238 381 16 16
|
||||||
icons/ArrowRight 0 411 16 16
|
icons/ArrowRight 255 381 16 16
|
||||||
icons/AspectRatio 17 411 16 16
|
icons/AspectRatio 272 381 16 16
|
||||||
icons/ButtonCheck 447 259 17 17
|
icons/ButtonCheck 153 363 17 17
|
||||||
icons/ButtonClipboard 465 259 17 17
|
icons/ButtonClipboard 171 363 17 17
|
||||||
icons/ButtonRandomize 483 259 17 17
|
icons/ButtonRandomize 189 363 17 17
|
||||||
icons/CPU 34 411 16 16
|
icons/CPU 289 381 16 16
|
||||||
icons/Card 51 411 16 16
|
icons/Card 306 381 16 16
|
||||||
icons/Close 0 496 15 14
|
icons/Close 0 451 15 14
|
||||||
icons/Code 68 411 16 16
|
icons/Code 323 381 16 16
|
||||||
icons/ComponentBus 85 411 16 16
|
icons/ComponentBus 340 381 16 16
|
||||||
icons/Copy 102 411 16 16
|
icons/Copy 357 381 16 16
|
||||||
icons/Cross 119 411 16 16
|
icons/Cross 374 381 16 16
|
||||||
icons/Delete 136 411 16 16
|
icons/Delete 391 381 16 16
|
||||||
icons/DragLMB 302 356 21 14
|
icons/DragLMB 351 330 21 14
|
||||||
icons/DragRMB 324 356 21 14
|
icons/DragRMB 373 330 21 14
|
||||||
icons/EEPROM 153 411 16 16
|
icons/EEPROM 408 381 16 16
|
||||||
icons/Edit 170 411 16 16
|
icons/Edit 425 381 16 16
|
||||||
icons/Eject 187 411 16 16
|
icons/Eject 442 381 16 16
|
||||||
icons/File 204 411 16 16
|
icons/File 459 381 16 16
|
||||||
icons/Floppy 221 411 16 16
|
icons/Floppy 476 381 16 16
|
||||||
icons/Folder 238 411 16 16
|
icons/Folder 493 381 16 16
|
||||||
icons/FolderSlash 255 411 16 16
|
icons/FolderSlash 510 381 16 16
|
||||||
icons/Grid 233 356 22 22
|
icons/Grid 187 330 22 22
|
||||||
icons/GridOff 256 356 22 22
|
icons/GridOff 210 330 22 22
|
||||||
icons/HDD 272 411 16 16
|
icons/HDD 527 381 16 16
|
||||||
icons/Home 279 356 22 22
|
icons/Home 233 330 22 22
|
||||||
icons/LMB 61 496 11 14
|
icons/LMB 71 466 11 14
|
||||||
icons/Label 289 411 16 16
|
icons/Label 544 381 16 16
|
||||||
icons/LinesHorizontal 306 411 16 16
|
icons/LinesHorizontal 561 381 16 16
|
||||||
icons/Link 323 411 16 16
|
icons/Link 578 381 16 16
|
||||||
icons/LinkSlash 340 411 16 16
|
icons/LinkSlash 595 381 16 16
|
||||||
icons/Memory 357 411 16 16
|
icons/Memory 612 381 16 16
|
||||||
icons/Microchip 374 411 16 16
|
icons/Microchip 629 381 16 16
|
||||||
icons/NA 391 411 16 16
|
icons/NA 646 381 16 16
|
||||||
icons/NotificationError 94 496 11 11
|
icons/NotificationError 95 466 11 11
|
||||||
icons/NotificationInfo 106 496 11 11
|
icons/NotificationInfo 107 466 11 11
|
||||||
icons/NotificationWarning 118 496 11 11
|
icons/NotificationWarning 119 466 11 11
|
||||||
icons/Pin 16 496 14 14
|
icons/Pin 26 466 14 14
|
||||||
icons/Plus 408 411 16 16
|
icons/Plus 663 381 16 16
|
||||||
icons/Power 425 411 16 16
|
icons/Power 680 381 16 16
|
||||||
icons/RMB 73 496 11 14
|
icons/RMB 83 466 11 14
|
||||||
icons/Restart 442 411 16 16
|
icons/Restart 697 381 16 16
|
||||||
icons/Save 459 411 16 16
|
icons/Save 714 381 16 16
|
||||||
icons/SaveAs 476 411 16 16
|
icons/SaveAs 731 381 16 16
|
||||||
icons/Server 493 411 16 16
|
icons/Server 748 381 16 16
|
||||||
icons/SettingsSound 447 277 12 17
|
icons/SettingsSound 0 466 12 17
|
||||||
icons/SettingsUI 460 277 12 17
|
icons/SettingsUI 13 466 12 17
|
||||||
icons/Tier0 0 428 16 16
|
icons/Tier0 765 381 16 16
|
||||||
icons/Tier1 17 428 16 16
|
icons/Tier1 782 381 16 16
|
||||||
icons/Tier2 34 428 16 16
|
icons/Tier2 799 381 16 16
|
||||||
icons/Tiers 51 428 16 16
|
icons/Tiers 816 381 16 16
|
||||||
icons/Unpin 31 496 14 14
|
icons/Unpin 41 466 14 14
|
||||||
icons/WaveLFSR 335 344 24 10
|
icons/WaveLFSR 121 434 24 10
|
||||||
icons/WaveNoise 360 344 24 10
|
icons/WaveNoise 146 434 24 10
|
||||||
icons/WaveSawtooth 385 344 24 10
|
icons/WaveSawtooth 171 434 24 10
|
||||||
icons/WaveSine 410 344 24 10
|
icons/WaveSine 196 434 24 10
|
||||||
icons/WaveSquare 435 344 24 10
|
icons/WaveSquare 221 434 24 10
|
||||||
icons/WaveTriangle 460 344 24 10
|
icons/WaveTriangle 246 434 24 10
|
||||||
icons/Window 68 428 16 16
|
icons/Window 833 381 16 16
|
||||||
icons/WireArrowLeft 264 496 4 8
|
icons/WireArrowLeft 2 538 4 8
|
||||||
icons/WireArrowRight 269 496 4 8
|
icons/WireArrowRight 7 538 4 8
|
||||||
items/APU0 305 208 16 96
|
items/APU0 85 305 16 96
|
||||||
items/APU1 322 208 16 96
|
items/APU1 102 305 16 96
|
||||||
items/APU2 339 208 16 96
|
items/APU2 119 305 16 96
|
||||||
items/CPU0 85 428 16 16
|
items/CPU0 850 381 16 16
|
||||||
items/CPU1 102 428 16 16
|
items/CPU1 867 381 16 16
|
||||||
items/CPU2 119 428 16 16
|
items/CPU2 884 381 16 16
|
||||||
items/CardBase 136 428 16 16
|
items/CardBase 901 381 16 16
|
||||||
items/CircuitBoard 153 428 16 16
|
items/CircuitBoard 918 381 16 16
|
||||||
items/ComponentBus0 170 428 16 16
|
items/ComponentBus0 935 381 16 16
|
||||||
items/ComponentBus1 187 428 16 16
|
items/ComponentBus1 952 381 16 16
|
||||||
items/ComponentBus2 204 428 16 16
|
items/ComponentBus2 969 381 16 16
|
||||||
items/ComponentBus3 221 428 16 16
|
items/ComponentBus3 986 381 16 16
|
||||||
items/DataCard0 434 0 16 128
|
items/DataCard0 0 305 16 128
|
||||||
items/DataCard1 451 0 16 128
|
items/DataCard1 17 305 16 128
|
||||||
items/DataCard2 468 0 16 128
|
items/DataCard2 34 305 16 128
|
||||||
items/DebugCard 238 428 16 16
|
items/DebugCard 1003 381 16 16
|
||||||
items/DiskDriveMountable 255 428 16 16
|
items/DiskDriveMountable 278 305 16 16
|
||||||
items/EEPROM 272 428 16 16
|
items/EEPROM 295 305 16 16
|
||||||
items/FloppyDisk_dyeBlack 289 428 16 16
|
items/FloppyDisk_dyeBlack 312 305 16 16
|
||||||
items/FloppyDisk_dyeBlue 306 428 16 16
|
items/FloppyDisk_dyeBlue 329 305 16 16
|
||||||
items/FloppyDisk_dyeBrown 323 428 16 16
|
items/FloppyDisk_dyeBrown 346 305 16 16
|
||||||
items/FloppyDisk_dyeCyan 340 428 16 16
|
items/FloppyDisk_dyeCyan 363 305 16 16
|
||||||
items/FloppyDisk_dyeGray 357 428 16 16
|
items/FloppyDisk_dyeGray 380 305 16 16
|
||||||
items/FloppyDisk_dyeGreen 374 428 16 16
|
items/FloppyDisk_dyeGreen 397 305 16 16
|
||||||
items/FloppyDisk_dyeLightBlue 391 428 16 16
|
items/FloppyDisk_dyeLightBlue 414 305 16 16
|
||||||
items/FloppyDisk_dyeLightGray 408 428 16 16
|
items/FloppyDisk_dyeLightGray 431 305 16 16
|
||||||
items/FloppyDisk_dyeLime 425 428 16 16
|
items/FloppyDisk_dyeLime 448 305 16 16
|
||||||
items/FloppyDisk_dyeMagenta 442 428 16 16
|
items/FloppyDisk_dyeMagenta 465 305 16 16
|
||||||
items/FloppyDisk_dyeOrange 459 428 16 16
|
items/FloppyDisk_dyeOrange 482 305 16 16
|
||||||
items/FloppyDisk_dyePink 476 428 16 16
|
items/FloppyDisk_dyePink 499 305 16 16
|
||||||
items/FloppyDisk_dyePurple 493 428 16 16
|
items/FloppyDisk_dyePurple 516 305 16 16
|
||||||
items/FloppyDisk_dyeRed 0 445 16 16
|
items/FloppyDisk_dyeRed 533 305 16 16
|
||||||
items/FloppyDisk_dyeWhite 17 445 16 16
|
items/FloppyDisk_dyeWhite 550 305 16 16
|
||||||
items/FloppyDisk_dyeYellow 34 445 16 16
|
items/FloppyDisk_dyeYellow 567 305 16 16
|
||||||
items/GraphicsCard0 51 445 16 16
|
items/GraphicsCard0 584 305 16 16
|
||||||
items/GraphicsCard1 68 445 16 16
|
items/GraphicsCard1 601 305 16 16
|
||||||
items/GraphicsCard2 85 445 16 16
|
items/GraphicsCard2 618 305 16 16
|
||||||
items/HardDiskDrive0 102 445 16 16
|
items/HardDiskDrive0 635 305 16 16
|
||||||
items/HardDiskDrive1 119 445 16 16
|
items/HardDiskDrive1 652 305 16 16
|
||||||
items/HardDiskDrive2 136 445 16 16
|
items/HardDiskDrive2 669 305 16 16
|
||||||
items/InternetCard 338 305 16 32
|
items/InternetCard 153 330 16 32
|
||||||
items/LinkedCard 356 208 16 96
|
items/LinkedCard 136 305 16 96
|
||||||
items/Memory0 153 445 16 16
|
items/Memory0 686 305 16 16
|
||||||
items/Memory1 170 445 16 16
|
items/Memory1 703 305 16 16
|
||||||
items/Memory2 187 445 16 16
|
items/Memory2 720 305 16 16
|
||||||
items/Memory3 204 445 16 16
|
items/Memory3 737 305 16 16
|
||||||
items/Memory4 221 445 16 16
|
items/Memory4 754 305 16 16
|
||||||
items/Memory5 238 445 16 16
|
items/Memory5 771 305 16 16
|
||||||
items/NetworkCard 255 445 16 16
|
items/NetworkCard 788 305 16 16
|
||||||
items/RedstoneCard0 272 445 16 16
|
items/OcelotCard 51 305 16 128
|
||||||
items/RedstoneCard1 289 445 16 16
|
items/RedstoneCard0 805 305 16 16
|
||||||
items/SelfDestructingCard 355 305 16 32
|
items/RedstoneCard1 822 305 16 16
|
||||||
items/Server0 306 445 16 16
|
items/SelfDestructingCard 170 330 16 32
|
||||||
items/Server1 323 445 16 16
|
items/Server0 839 305 16 16
|
||||||
items/Server2 340 445 16 16
|
items/Server1 856 305 16 16
|
||||||
items/Server3 357 445 16 16
|
items/Server2 873 305 16 16
|
||||||
items/SoundCard 485 0 16 128
|
items/Server3 890 305 16 16
|
||||||
items/WirelessNetworkCard0 374 445 16 16
|
items/SoundCard 68 305 16 128
|
||||||
items/WirelessNetworkCard1 391 445 16 16
|
items/WirelessNetworkCard0 907 305 16 16
|
||||||
light-panel/BookmarkLeft 328 379 18 14
|
items/WirelessNetworkCard1 924 305 16 16
|
||||||
light-panel/BookmarkRight 346 356 20 14
|
light-panel/BookmarkLeft 102 434 18 14
|
||||||
light-panel/BorderB 282 498 4 4
|
light-panel/BookmarkRight 207 363 20 14
|
||||||
light-panel/BorderL 372 498 4 2
|
light-panel/BorderB 13 547 4 4
|
||||||
light-panel/BorderR 287 498 4 4
|
light-panel/BorderL 103 547 4 2
|
||||||
light-panel/BorderT 292 498 4 4
|
light-panel/BorderR 18 547 4 4
|
||||||
light-panel/CornerBL 297 498 4 4
|
light-panel/BorderT 23 547 4 4
|
||||||
light-panel/CornerBR 302 498 4 4
|
light-panel/CornerBL 28 547 4 4
|
||||||
light-panel/CornerTL 307 498 4 4
|
light-panel/CornerBR 33 547 4 4
|
||||||
light-panel/CornerTR 312 498 4 4
|
light-panel/CornerTL 38 547 4 4
|
||||||
light-panel/Fill 507 484 2 2
|
light-panel/CornerTR 43 547 4 4
|
||||||
light-panel/Vent 335 305 2 38
|
light-panel/Fill 6 558 2 2
|
||||||
nodes/Cable 221 496 8 8
|
light-panel/Vent 0 499 2 38
|
||||||
nodes/Camera 408 445 16 16
|
nodes/Cable 21 510 8 8
|
||||||
nodes/Chest 46 496 14 14
|
nodes/Camera 941 305 16 16
|
||||||
nodes/HologramProjector0 425 445 16 16
|
nodes/Chest 56 466 14 14
|
||||||
nodes/HologramProjector1 442 445 16 16
|
nodes/HologramProjector0 958 305 16 16
|
||||||
nodes/IronNoteBlock 459 445 16 16
|
nodes/HologramProjector1 975 305 16 16
|
||||||
nodes/Lamp 476 445 16 16
|
nodes/IronNoteBlock 992 305 16 16
|
||||||
nodes/LampFrame 493 445 16 16
|
nodes/Lamp 85 402 16 16
|
||||||
nodes/LampGlow 305 0 128 128
|
nodes/LampFrame 102 402 16 16
|
||||||
nodes/NewNode 0 462 16 16
|
nodes/LampGlow 305 106 128 128
|
||||||
nodes/NoteBlock 17 462 16 16
|
nodes/NewNode 119 402 16 16
|
||||||
nodes/OpenFMRadio 34 462 16 16
|
nodes/NoteBlock 136 402 16 16
|
||||||
nodes/Relay 51 462 16 16
|
nodes/OpenFMRadio 153 402 16 16
|
||||||
nodes/computer/Activity 68 462 16 16
|
nodes/Relay 170 402 16 16
|
||||||
nodes/computer/Default 85 462 16 16
|
nodes/computer/Activity 187 402 16 16
|
||||||
nodes/computer/Error 102 462 16 16
|
nodes/computer/Default 204 402 16 16
|
||||||
nodes/computer/On 119 462 16 16
|
nodes/computer/Error 221 402 16 16
|
||||||
nodes/disk-drive/Activity 136 462 16 16
|
nodes/computer/On 238 402 16 16
|
||||||
nodes/disk-drive/Default 153 462 16 16
|
nodes/disk-drive/Activity 255 402 16 16
|
||||||
nodes/disk-drive/Floppy 170 462 16 16
|
nodes/disk-drive/Default 272 402 16 16
|
||||||
nodes/rack/Default 187 462 16 16
|
nodes/disk-drive/Floppy 289 402 16 16
|
||||||
nodes/rack/Empty 204 462 16 16
|
nodes/rack/Default 306 402 16 16
|
||||||
nodes/rack/drive/0/Activity 221 462 16 16
|
nodes/rack/Empty 323 402 16 16
|
||||||
nodes/rack/drive/0/Default 238 462 16 16
|
nodes/rack/drive/0/Activity 340 402 16 16
|
||||||
nodes/rack/drive/0/Floppy 255 462 16 16
|
nodes/rack/drive/0/Default 357 402 16 16
|
||||||
nodes/rack/drive/1/Activity 272 462 16 16
|
nodes/rack/drive/0/Floppy 374 402 16 16
|
||||||
nodes/rack/drive/1/Default 289 462 16 16
|
nodes/rack/drive/1/Activity 391 402 16 16
|
||||||
nodes/rack/drive/1/Floppy 306 462 16 16
|
nodes/rack/drive/1/Default 408 402 16 16
|
||||||
nodes/rack/drive/2/Activity 323 462 16 16
|
nodes/rack/drive/1/Floppy 425 402 16 16
|
||||||
nodes/rack/drive/2/Default 340 462 16 16
|
nodes/rack/drive/2/Activity 442 402 16 16
|
||||||
nodes/rack/drive/2/Floppy 357 462 16 16
|
nodes/rack/drive/2/Default 459 402 16 16
|
||||||
nodes/rack/drive/3/Activity 374 462 16 16
|
nodes/rack/drive/2/Floppy 476 402 16 16
|
||||||
nodes/rack/drive/3/Default 391 462 16 16
|
nodes/rack/drive/3/Activity 493 402 16 16
|
||||||
nodes/rack/drive/3/Floppy 408 462 16 16
|
nodes/rack/drive/3/Default 510 402 16 16
|
||||||
nodes/rack/drive/Floppy 425 462 16 16
|
nodes/rack/drive/3/Floppy 527 402 16 16
|
||||||
nodes/rack/server/0/Activity 442 462 16 16
|
nodes/rack/drive/Floppy 544 402 16 16
|
||||||
nodes/rack/server/0/Default 459 462 16 16
|
nodes/rack/server/0/Activity 561 402 16 16
|
||||||
nodes/rack/server/0/Error 476 462 16 16
|
nodes/rack/server/0/Default 578 402 16 16
|
||||||
nodes/rack/server/0/On 493 462 16 16
|
nodes/rack/server/0/Error 595 402 16 16
|
||||||
nodes/rack/server/1/Activity 0 479 16 16
|
nodes/rack/server/0/On 612 402 16 16
|
||||||
nodes/rack/server/1/Default 17 479 16 16
|
nodes/rack/server/1/Activity 629 402 16 16
|
||||||
nodes/rack/server/1/Error 34 479 16 16
|
nodes/rack/server/1/Default 646 402 16 16
|
||||||
nodes/rack/server/1/On 51 479 16 16
|
nodes/rack/server/1/Error 663 402 16 16
|
||||||
nodes/rack/server/2/Activity 68 479 16 16
|
nodes/rack/server/1/On 680 402 16 16
|
||||||
nodes/rack/server/2/Default 85 479 16 16
|
nodes/rack/server/2/Activity 697 402 16 16
|
||||||
nodes/rack/server/2/Error 102 479 16 16
|
nodes/rack/server/2/Default 714 402 16 16
|
||||||
nodes/rack/server/2/On 119 479 16 16
|
nodes/rack/server/2/Error 731 402 16 16
|
||||||
nodes/rack/server/3/Activity 136 479 16 16
|
nodes/rack/server/2/On 748 402 16 16
|
||||||
nodes/rack/server/3/Default 153 479 16 16
|
nodes/rack/server/3/Activity 765 402 16 16
|
||||||
nodes/rack/server/3/Error 170 479 16 16
|
nodes/rack/server/3/Default 782 402 16 16
|
||||||
nodes/rack/server/3/On 187 479 16 16
|
nodes/rack/server/3/Error 799 402 16 16
|
||||||
nodes/screen/BottomLeft 204 479 16 16
|
nodes/rack/server/3/On 816 402 16 16
|
||||||
nodes/screen/BottomMiddle 221 479 16 16
|
nodes/screen/BottomLeft 833 402 16 16
|
||||||
nodes/screen/BottomRight 238 479 16 16
|
nodes/screen/BottomMiddle 850 402 16 16
|
||||||
nodes/screen/ColumnBottom 255 479 16 16
|
nodes/screen/BottomRight 867 402 16 16
|
||||||
nodes/screen/ColumnMiddle 272 479 16 16
|
nodes/screen/ColumnBottom 884 402 16 16
|
||||||
nodes/screen/ColumnTop 289 479 16 16
|
nodes/screen/ColumnMiddle 901 402 16 16
|
||||||
nodes/screen/Middle 306 479 16 16
|
nodes/screen/ColumnTop 918 402 16 16
|
||||||
nodes/screen/MiddleLeft 323 479 16 16
|
nodes/screen/Middle 935 402 16 16
|
||||||
nodes/screen/MiddleRight 340 479 16 16
|
nodes/screen/MiddleLeft 952 402 16 16
|
||||||
nodes/screen/PowerOnOverlay 357 479 16 16
|
nodes/screen/MiddleRight 969 402 16 16
|
||||||
nodes/screen/RowLeft 374 479 16 16
|
nodes/screen/PowerOnOverlay 986 402 16 16
|
||||||
nodes/screen/RowMiddle 391 479 16 16
|
nodes/screen/RowLeft 1003 402 16 16
|
||||||
nodes/screen/RowRight 408 479 16 16
|
nodes/screen/RowMiddle 0 434 16 16
|
||||||
nodes/screen/Standalone 425 479 16 16
|
nodes/screen/RowRight 17 434 16 16
|
||||||
nodes/screen/TopLeft 442 479 16 16
|
nodes/screen/Standalone 34 434 16 16
|
||||||
nodes/screen/TopMiddle 459 479 16 16
|
nodes/screen/TopLeft 51 434 16 16
|
||||||
nodes/screen/TopRight 476 479 16 16
|
nodes/screen/TopMiddle 68 434 16 16
|
||||||
panel/BorderB 317 498 4 4
|
nodes/screen/TopRight 85 434 16 16
|
||||||
panel/BorderL 377 498 4 2
|
panel/BorderB 48 547 4 4
|
||||||
panel/BorderR 322 498 4 4
|
panel/BorderL 108 547 4 2
|
||||||
panel/BorderT 327 498 4 4
|
panel/BorderR 53 547 4 4
|
||||||
panel/CornerBL 332 498 4 4
|
panel/BorderT 58 547 4 4
|
||||||
panel/CornerBR 337 498 4 4
|
panel/CornerBL 63 547 4 4
|
||||||
panel/CornerTL 342 498 4 4
|
panel/CornerBR 68 547 4 4
|
||||||
panel/CornerTR 347 498 4 4
|
panel/CornerTL 73 547 4 4
|
||||||
panel/Fill 493 489 2 2
|
panel/CornerTR 78 547 4 4
|
||||||
particles/Note 192 496 7 10
|
panel/Fill 9 558 2 2
|
||||||
screen/BorderB 274 496 2 8
|
particles/Note 21 499 7 10
|
||||||
screen/BorderT 200 496 2 10
|
screen/BorderB 5 547 2 8
|
||||||
screen/CornerBL 230 496 8 8
|
screen/BorderT 2 547 2 10
|
||||||
screen/CornerBR 239 496 8 8
|
screen/CornerBL 30 510 8 8
|
||||||
screen/CornerTL 174 496 8 10
|
screen/CornerBR 39 510 8 8
|
||||||
screen/CornerTR 183 496 8 10
|
screen/CornerTL 3 499 8 10
|
||||||
window/BorderDark 510 479 1 4
|
screen/CornerTR 12 499 8 10
|
||||||
window/BorderLight 493 484 1 4
|
window/BorderDark 2 558 1 4
|
||||||
window/CornerBL 352 498 4 4
|
window/BorderLight 4 558 1 4
|
||||||
window/CornerBR 357 498 4 4
|
window/CornerBL 83 547 4 4
|
||||||
window/CornerTL 362 498 4 4
|
window/CornerBR 88 547 4 4
|
||||||
window/CornerTR 367 498 4 4
|
window/CornerTL 93 547 4 4
|
||||||
window/OpenFMRadio 0 305 232 105
|
window/CornerTR 98 547 4 4
|
||||||
window/case/Motherboard 406 129 79 70
|
window/OpenFMRadio 305 0 232 105
|
||||||
window/rack/Lines 373 208 73 91
|
window/case/Motherboard 612 0 79 70
|
||||||
window/rack/Motherboard 305 129 100 78
|
window/rack/Lines 538 0 73 91
|
||||||
window/rack/NetworkBack 496 489 1 2
|
window/rack/Motherboard 434 106 100 78
|
||||||
window/rack/NetworkBottom 498 489 1 2
|
window/rack/NetworkBack 20 552 1 2
|
||||||
window/rack/NetworkConnector 500 489 1 2
|
window/rack/NetworkBottom 22 552 1 2
|
||||||
window/rack/NetworkLeft 502 489 1 2
|
window/rack/NetworkConnector 24 552 1 2
|
||||||
window/rack/NetworkRight 504 489 1 2
|
window/rack/NetworkLeft 26 552 1 2
|
||||||
window/rack/NetworkTop 506 489 1 2
|
window/rack/NetworkRight 28 552 1 2
|
||||||
window/rack/NodeBack 277 496 5 1
|
window/rack/NetworkTop 30 552 1 2
|
||||||
window/rack/NodeBottom 283 496 5 1
|
window/rack/NodeBack 113 547 5 1
|
||||||
window/rack/NodeLeft 289 496 5 1
|
window/rack/NodeBottom 119 547 5 1
|
||||||
window/rack/NodeRight 295 496 5 1
|
window/rack/NodeLeft 125 547 5 1
|
||||||
window/rack/NodeTop 301 496 5 1
|
window/rack/NodeRight 131 547 5 1
|
||||||
window/rack/SideBack 495 484 1 3
|
window/rack/NodeTop 137 547 5 1
|
||||||
window/rack/SideBottom 497 484 1 3
|
window/rack/SideBack 8 552 1 3
|
||||||
window/rack/SideConnector 499 484 1 3
|
window/rack/SideBottom 10 552 1 3
|
||||||
window/rack/SideLeft 501 484 1 3
|
window/rack/SideConnector 12 552 1 3
|
||||||
window/rack/SideRight 503 484 1 3
|
window/rack/SideLeft 14 552 1 3
|
||||||
window/rack/SideTop 505 484 1 3
|
window/rack/SideRight 16 552 1 3
|
||||||
|
window/rack/SideTop 18 552 1 3
|
||||||
|
|||||||
61
src/main/scala/ocelot/desktop/entity/OcelotCard.scala
Normal file
61
src/main/scala/ocelot/desktop/entity/OcelotCard.scala
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package ocelot.desktop.entity
|
||||||
|
|
||||||
|
import ocelot.desktop.entity.OcelotCard.LogEvent
|
||||||
|
import totoro.ocelot.brain.Constants
|
||||||
|
import totoro.ocelot.brain.entity.machine.{Arguments, Callback, Context}
|
||||||
|
import totoro.ocelot.brain.entity.traits.DeviceInfo.{DeviceAttribute, DeviceClass}
|
||||||
|
import totoro.ocelot.brain.entity.traits.{DeviceInfo, Entity, Environment, Tiered, result}
|
||||||
|
import totoro.ocelot.brain.event.{EventBus, NodeEvent}
|
||||||
|
import totoro.ocelot.brain.network.{Network, Node, Visibility}
|
||||||
|
import totoro.ocelot.brain.util.Tier
|
||||||
|
import totoro.ocelot.brain.util.Tier.Tier
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
class OcelotCard extends Entity with Environment with DeviceInfo with Tiered {
|
||||||
|
override val node: Node = Network.newNode(this, Visibility.Neighbors)
|
||||||
|
.withComponent("ocelot", Visibility.Neighbors)
|
||||||
|
.create()
|
||||||
|
|
||||||
|
override def tier: Tier = Tier.One
|
||||||
|
|
||||||
|
private final lazy val deviceInfo = Map(
|
||||||
|
DeviceAttribute.Class -> DeviceClass.Generic,
|
||||||
|
DeviceAttribute.Description -> "Yarn ball manipulator",
|
||||||
|
DeviceAttribute.Vendor -> Constants.DeviceInfo.DefaultVendor,
|
||||||
|
DeviceAttribute.Product -> "Catbus",
|
||||||
|
)
|
||||||
|
|
||||||
|
override def getDeviceInfo: Map[String, String] = deviceInfo
|
||||||
|
|
||||||
|
@Callback(direct = true, doc = """function(message: string) -- Logs a message to the Ocelot console.""")
|
||||||
|
def log(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
val message = args.checkString(0)
|
||||||
|
EventBus.send(LogEvent(node.address, message))
|
||||||
|
result()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(direct = true, doc = """function(): integer -- Returns the current Unix timestamp (UTC, in milliseconds).""")
|
||||||
|
def getTimestamp(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
result(Instant.now().toEpochMilli)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(direct = true, doc = """function(): integer -- Returns a high-resolution timer value (in nanoseconds).""")
|
||||||
|
def getInstant(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
result(System.nanoTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(direct = true, doc = """function(): number -- Returns the remaining call budget.""")
|
||||||
|
def getRemainingCallBudget(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
result(context.getRemainingCallBudget)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Callback(direct = true, doc = """function(): number -- Returns the maximum call budget.""")
|
||||||
|
def getMaxCallBudget(context: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
result(context.getMaxCallBudget)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object OcelotCard {
|
||||||
|
case class LogEvent(address: String, message: String) extends NodeEvent
|
||||||
|
}
|
||||||
@ -220,7 +220,7 @@ class Graphics(private var scalingFactor: Float) extends Logging with Resource {
|
|||||||
def text(x: Float, y: Float, text: String, shrink: Int = 0): Unit = {
|
def text(x: Float, y: Float, text: String, shrink: Int = 0): Unit = {
|
||||||
var ox = x
|
var ox = x
|
||||||
|
|
||||||
for (c <- text) {
|
text.codePoints().forEach { c =>
|
||||||
char(ox, y, c)
|
char(ox, y, c)
|
||||||
ox += _font.charWidth(c) - shrink
|
ox += _font.charWidth(c) - shrink
|
||||||
}
|
}
|
||||||
@ -329,7 +329,7 @@ class Graphics(private var scalingFactor: Float) extends Logging with Resource {
|
|||||||
|
|
||||||
val uvTransform = Transform2D.translate(spriteRect.x, spriteRect.y) >>
|
val uvTransform = Transform2D.translate(spriteRect.x, spriteRect.y) >>
|
||||||
(if (fixUV)
|
(if (fixUV)
|
||||||
Transform2D.scale(spriteRect.w - 0.25f / 512, spriteRect.h - 0.25f / 512)
|
Transform2D.scale(spriteRect.w - 0.25f / 1024, spriteRect.h - 0.25f / 1024)
|
||||||
else
|
else
|
||||||
Transform2D.scale(spriteRect.w, spriteRect.h))
|
Transform2D.scale(spriteRect.w, spriteRect.h))
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,8 @@ object IconSource {
|
|||||||
|
|
||||||
val SelfDestructingCard: IconSource = IconSource("items/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard))
|
val SelfDestructingCard: IconSource = IconSource("items/SelfDestructingCard", animation = Some(Animations.SelfDestructingCard))
|
||||||
|
|
||||||
|
val OcelotCard: IconSource = IconSource("items/OcelotCard", animation = Some(Animations.OcelotCard))
|
||||||
|
|
||||||
val HardDiskDrive: Tier => IconSource = { tier =>
|
val HardDiskDrive: Tier => IconSource = { tier =>
|
||||||
IconSource(s"items/HardDiskDrive${tier.id}")
|
IconSource(s"items/HardDiskDrive${tier.id}")
|
||||||
}
|
}
|
||||||
@ -101,6 +103,9 @@ object IconSource {
|
|||||||
(0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f))
|
(0, 4f), (1, 4f), (2, 4f), (3, 4f), (4, 4f), (5, 4f), (6, 4f), (7, 4f))
|
||||||
|
|
||||||
val SelfDestructingCard: Animation = Array((0, 4f), (1, 4f))
|
val SelfDestructingCard: Animation = Array((0, 4f), (1, 4f))
|
||||||
|
|
||||||
|
val OcelotCard: Animation = Array(
|
||||||
|
(0, 12f), (1, 4f), (2, 4f), (3, 4f), (4, 5f), (5, 6f), (0, 9f), (6, 4f), (7, 3f))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------- Ocelot interface icons -----------------------
|
// ----------------------- Ocelot interface icons -----------------------
|
||||||
|
|||||||
@ -139,6 +139,7 @@ object Items extends Logging {
|
|||||||
}
|
}
|
||||||
registerSingleton(SoundCardItem.Factory)
|
registerSingleton(SoundCardItem.Factory)
|
||||||
registerSingleton(SelfDestructingCardItem.Factory)
|
registerSingleton(SelfDestructingCardItem.Factory)
|
||||||
|
registerSingleton(OcelotCardItem.Factory)
|
||||||
|
|
||||||
registerTiered("Server", Tier.One to Tier.Creative)(new ServerItem.Factory(_))
|
registerTiered("Server", Tier.One to Tier.Creative)(new ServerItem.Factory(_))
|
||||||
registerTiered("Component bus", Tier.One to Tier.Creative)(new ComponentBusItem.Factory(_))
|
registerTiered("Component bus", Tier.One to Tier.Creative)(new ComponentBusItem.Factory(_))
|
||||||
|
|||||||
@ -0,0 +1,104 @@
|
|||||||
|
package ocelot.desktop.inventory.item
|
||||||
|
|
||||||
|
import ocelot.desktop.ColorScheme
|
||||||
|
import ocelot.desktop.color.Color
|
||||||
|
import ocelot.desktop.entity.OcelotCard
|
||||||
|
import ocelot.desktop.graphics.IconSource
|
||||||
|
import ocelot.desktop.inventory.item.OcelotCardItem.MessagesTag
|
||||||
|
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
|
||||||
|
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
|
||||||
|
import ocelot.desktop.ui.event.BrainEvent
|
||||||
|
import ocelot.desktop.ui.widget.card.OcelotCardWindow
|
||||||
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
||||||
|
import ocelot.desktop.ui.widget.window.Windowed
|
||||||
|
import totoro.ocelot.brain.nbt.ExtendedNBT.extendNBTTagList
|
||||||
|
import totoro.ocelot.brain.nbt.{NBT, NBTBase, NBTTagCompound, NBTTagString}
|
||||||
|
import totoro.ocelot.brain.util.Tier
|
||||||
|
import totoro.ocelot.brain.util.Tier.Tier
|
||||||
|
|
||||||
|
import scala.collection.IndexedSeqView
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
import scala.jdk.CollectionConverters.BufferHasAsJava
|
||||||
|
|
||||||
|
class OcelotCardItem(val ocelotCard: OcelotCard)
|
||||||
|
extends Item
|
||||||
|
with ComponentItem
|
||||||
|
with PersistableItem
|
||||||
|
with CardItem
|
||||||
|
with Windowed[OcelotCardWindow] {
|
||||||
|
|
||||||
|
private val _messages: ArrayBuffer[String] = ArrayBuffer.empty
|
||||||
|
|
||||||
|
def messages: IndexedSeqView[String] = _messages.view
|
||||||
|
|
||||||
|
eventHandlers += {
|
||||||
|
case BrainEvent(OcelotCard.LogEvent(_, message)) =>
|
||||||
|
addMessage(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def createWindow(): OcelotCardWindow = new OcelotCardWindow(this)
|
||||||
|
|
||||||
|
override def component: OcelotCard = ocelotCard
|
||||||
|
|
||||||
|
override def tooltipNameColor: Color = ColorScheme("OcelotCardTooltip")
|
||||||
|
|
||||||
|
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||||
|
menu.addEntry(ContextMenuEntry("Open console", IconSource.Window) {
|
||||||
|
window.open()
|
||||||
|
})
|
||||||
|
|
||||||
|
menu.addSeparator()
|
||||||
|
|
||||||
|
super.fillRmbMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def load(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.load(nbt)
|
||||||
|
|
||||||
|
clear()
|
||||||
|
addMessages(nbt.getTagList(MessagesTag, NBT.TAG_STRING).iterator[NBTTagString].map(_.getString))
|
||||||
|
}
|
||||||
|
|
||||||
|
override def save(nbt: NBTTagCompound): Unit = {
|
||||||
|
super.save(nbt)
|
||||||
|
nbt.setTagList(MessagesTag, _messages.map(new NBTTagString(_).asInstanceOf[NBTBase]).asJava)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def factory: ItemFactory = OcelotCardItem.Factory
|
||||||
|
|
||||||
|
def clear(): Unit = {
|
||||||
|
_messages.clear()
|
||||||
|
window.onMessagesCleared()
|
||||||
|
}
|
||||||
|
|
||||||
|
private def addMessage(message: String): Unit = {
|
||||||
|
_messages += message
|
||||||
|
window.onMessagesAdded(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def addMessages(messages: Iterator[String]): Unit = {
|
||||||
|
val currentSize = this._messages.length
|
||||||
|
this._messages ++= messages
|
||||||
|
window.onMessagesAdded(this._messages.length - currentSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object OcelotCardItem {
|
||||||
|
val MessagesTag = "messages"
|
||||||
|
|
||||||
|
object Factory extends ItemFactory {
|
||||||
|
override type I = OcelotCardItem
|
||||||
|
|
||||||
|
override def itemClass: Class[I] = classOf
|
||||||
|
|
||||||
|
override def name: String = "Ocelot Card"
|
||||||
|
|
||||||
|
override def tier: Option[Tier] = Some(Tier.One)
|
||||||
|
|
||||||
|
override def icon: IconSource = IconSource.OcelotCard
|
||||||
|
|
||||||
|
override def build(): OcelotCardItem = new OcelotCardItem(new OcelotCard)
|
||||||
|
|
||||||
|
override def recoverers: Iterable[ItemRecoverer[_, _]] = Nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,28 +1,26 @@
|
|||||||
package ocelot.desktop.node
|
package ocelot.desktop.node
|
||||||
|
|
||||||
import ocelot.desktop.inventory.{Item, SyncedInventory}
|
import ocelot.desktop.inventory.SyncedInventory
|
||||||
|
import ocelot.desktop.inventory.traits.ComponentItem
|
||||||
import ocelot.desktop.ui.event.Event
|
import ocelot.desktop.ui.event.Event
|
||||||
import totoro.ocelot.brain.entity.traits.{Entity, Environment}
|
import totoro.ocelot.brain.entity.traits.{Entity, Environment}
|
||||||
|
|
||||||
abstract class SyncedInventoryEntityNode(entity: Entity with Environment)
|
abstract class SyncedInventoryEntityNode(entity: Entity with Environment)
|
||||||
extends EntityNode(entity)
|
extends EntityNode(entity)
|
||||||
with SyncedInventory
|
with SyncedInventory {
|
||||||
{
|
|
||||||
override def shouldReceiveEventsFor(address: String): Boolean =
|
override def shouldReceiveEventsFor(address: String): Boolean =
|
||||||
super.shouldReceiveEventsFor(address) ||
|
super.shouldReceiveEventsFor(address) ||
|
||||||
brainInventory.inventory.entities.exists {
|
inventoryIterator
|
||||||
case env: Environment => env.node.address == address
|
.flatMap(_.get)
|
||||||
}
|
.collect { case item: ComponentItem => item }
|
||||||
|
.exists(_.component.node.address == address)
|
||||||
|
|
||||||
override def handleEvent(event: Event): Unit = {
|
override def handleEvent(event: Event): Unit = {
|
||||||
super.handleEvent(event)
|
super.handleEvent(event)
|
||||||
|
|
||||||
inventoryIterator.foreach(slot =>
|
for (slot <- inventoryIterator; item <- slot.get) {
|
||||||
slot.get match {
|
item.handleEvent(event)
|
||||||
case Some(item: Item) =>
|
}
|
||||||
item.handleEvent(event)
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
94
src/main/scala/ocelot/desktop/ui/widget/LogWidget.scala
Normal file
94
src/main/scala/ocelot/desktop/ui/widget/LogWidget.scala
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package ocelot.desktop.ui.widget
|
||||||
|
|
||||||
|
import ocelot.desktop.ColorScheme
|
||||||
|
import ocelot.desktop.geometry.{Padding2D, Size2D}
|
||||||
|
import ocelot.desktop.graphics.Graphics
|
||||||
|
import ocelot.desktop.ui.layout.{Layout, LinearLayout}
|
||||||
|
import ocelot.desktop.ui.widget.LogWidget.{BorderThickness, EntryPadding}
|
||||||
|
import ocelot.desktop.util.{DrawUtils, Orientation}
|
||||||
|
|
||||||
|
import scala.collection.immutable.ArraySeq
|
||||||
|
|
||||||
|
abstract class LogWidget extends Widget {
|
||||||
|
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||||
|
|
||||||
|
private val messageListWidget = new Widget {
|
||||||
|
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||||
|
}
|
||||||
|
|
||||||
|
children :+= new PaddingBox(
|
||||||
|
new ScrollView(messageListWidget),
|
||||||
|
Padding2D.equal(BorderThickness),
|
||||||
|
)
|
||||||
|
|
||||||
|
protected def messages: Iterable[String]
|
||||||
|
|
||||||
|
protected def textWidth: Int
|
||||||
|
|
||||||
|
override def minimumSize: Size2D = Size2D(
|
||||||
|
textWidth * 8 +
|
||||||
|
2 * BorderThickness + // entry border (left + right)
|
||||||
|
2 * EntryPadding +
|
||||||
|
2 * BorderThickness, // outer border (left + right)
|
||||||
|
|
||||||
|
16 +
|
||||||
|
2 * BorderThickness + // entry border (top + bottom)
|
||||||
|
2 * EntryPadding +
|
||||||
|
2 * BorderThickness, // outer border (top + bottom)
|
||||||
|
)
|
||||||
|
|
||||||
|
def onMessagesAdded(count: Int): Unit = {
|
||||||
|
for (message <- messages.drop(messages.size - count)) {
|
||||||
|
messageListWidget.children :+= new Entry(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
recalculateBoundsAndRelayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
def onMessagesCleared(): Unit = {
|
||||||
|
messageListWidget.children = ArraySeq.empty
|
||||||
|
recalculateBoundsAndRelayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
override def draw(g: Graphics): Unit = {
|
||||||
|
g.rect(bounds, ColorScheme("LogBackground"))
|
||||||
|
DrawUtils.ring(g, bounds.x, bounds.y, bounds.w, bounds.h, BorderThickness, ColorScheme("LogBorder"))
|
||||||
|
|
||||||
|
super.draw(g)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Entry(val message: String) extends Widget {
|
||||||
|
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||||
|
|
||||||
|
children :+= new PaddingBox(
|
||||||
|
new Text {
|
||||||
|
override def text: String = message
|
||||||
|
|
||||||
|
override def wrapWidth: Option[Int] = Some(LogWidget.this.textWidth)
|
||||||
|
},
|
||||||
|
Padding2D.equal(EntryPadding + BorderThickness),
|
||||||
|
)
|
||||||
|
|
||||||
|
override def draw(g: Graphics): Unit = {
|
||||||
|
val innerBounds = bounds.inflate(-EntryPadding)
|
||||||
|
val ringBounds = innerBounds.inflate(BorderThickness)
|
||||||
|
g.rect(innerBounds, ColorScheme("LogEntryBackground"))
|
||||||
|
DrawUtils.ring(
|
||||||
|
g,
|
||||||
|
ringBounds.x,
|
||||||
|
ringBounds.y,
|
||||||
|
ringBounds.w,
|
||||||
|
ringBounds.h,
|
||||||
|
BorderThickness,
|
||||||
|
ColorScheme("LogEntryBorder"),
|
||||||
|
)
|
||||||
|
|
||||||
|
super.draw(g)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object LogWidget {
|
||||||
|
val BorderThickness = 2
|
||||||
|
val EntryPadding = 4
|
||||||
|
}
|
||||||
169
src/main/scala/ocelot/desktop/ui/widget/Text.scala
Normal file
169
src/main/scala/ocelot/desktop/ui/widget/Text.scala
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package ocelot.desktop.ui.widget
|
||||||
|
|
||||||
|
import ocelot.desktop.ColorScheme
|
||||||
|
import ocelot.desktop.color.Color
|
||||||
|
import ocelot.desktop.geometry.Size2D
|
||||||
|
import ocelot.desktop.graphics.Graphics
|
||||||
|
import ocelot.desktop.ui.widget.Text.{CharHeight, getWidth, wrap}
|
||||||
|
import totoro.ocelot.brain.util.FontUtils
|
||||||
|
|
||||||
|
import scala.collection.mutable.ArrayBuffer
|
||||||
|
|
||||||
|
class Text extends Widget {
|
||||||
|
def text: String = ""
|
||||||
|
|
||||||
|
private var cachedText = ""
|
||||||
|
private var cachedWrapWidth = None: Option[Int]
|
||||||
|
private var cachedLines = ArrayBuffer.empty[String]
|
||||||
|
private var cachedWidth = 0
|
||||||
|
|
||||||
|
def color: Color = ColorScheme("Label")
|
||||||
|
|
||||||
|
def wrapWidth: Option[Int] = None
|
||||||
|
|
||||||
|
private def recomputeIfNeeded(): Unit = {
|
||||||
|
if (text != cachedText || cachedWrapWidth != wrapWidth) {
|
||||||
|
recomputeProperties()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final def textWidth: Int = {
|
||||||
|
recomputeIfNeeded()
|
||||||
|
cachedWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
final def textHeight: Int = {
|
||||||
|
recomputeIfNeeded()
|
||||||
|
cachedLines.length
|
||||||
|
}
|
||||||
|
|
||||||
|
final def textLines: Iterable[String] = {
|
||||||
|
recomputeIfNeeded()
|
||||||
|
cachedLines
|
||||||
|
}
|
||||||
|
|
||||||
|
override def minimumSize: Size2D = Size2D(textWidth, CharHeight * (textHeight max 1))
|
||||||
|
override def maximumSize: Size2D = minimumSize.copy(width = Float.PositiveInfinity)
|
||||||
|
|
||||||
|
override def draw(g: Graphics): Unit = {
|
||||||
|
g.background = Color.Transparent
|
||||||
|
g.foreground = color
|
||||||
|
|
||||||
|
for ((line, idx) <- textLines.zipWithIndex) {
|
||||||
|
g.text(position.x, position.y + idx * CharHeight, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def recomputeProperties(): Unit = {
|
||||||
|
cachedText = text
|
||||||
|
cachedWrapWidth = wrapWidth
|
||||||
|
cachedLines = wrap(cachedText, cachedWrapWidth)
|
||||||
|
cachedWidth = getWidth(cachedLines)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Text {
|
||||||
|
private val CharHeight = 16
|
||||||
|
|
||||||
|
private def getWidth(codepoint: Int): Int = FontUtils.wcwidth(codepoint)
|
||||||
|
|
||||||
|
private def getWidth(line: String): Int =
|
||||||
|
line.codePoints().map(getWidth).sum()
|
||||||
|
|
||||||
|
private def getWidth(lines: Iterable[String]): Int =
|
||||||
|
lines.iterator.map(getWidth).maxOption.getOrElse(0)
|
||||||
|
|
||||||
|
private def wrap(text: String, wrapWidth: Option[Int]): ArrayBuffer[String] = {
|
||||||
|
val lines = text.linesIterator
|
||||||
|
.flatMap(line => wrapWidth match {
|
||||||
|
case Some(wrapWidth) if getWidth(line) > wrapWidth => wrapLine(line, wrapWidth)
|
||||||
|
case _ => Some(line)
|
||||||
|
})
|
||||||
|
.to(ArrayBuffer)
|
||||||
|
|
||||||
|
val lastNonEmptyLineIdx = lines.lastIndexWhere(_.nonEmpty)
|
||||||
|
lines.takeInPlace(lastNonEmptyLineIdx + 1)
|
||||||
|
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
|
||||||
|
private def wrapLine(line: String, wrapWidth: Int): Iterable[String] = {
|
||||||
|
// adapted from cheburator's message splitter
|
||||||
|
|
||||||
|
val lines = ArrayBuffer.empty[String]
|
||||||
|
|
||||||
|
var lineStart = 0
|
||||||
|
var pos = -1
|
||||||
|
var lineWidth = 0
|
||||||
|
var lastSpacePos = -1
|
||||||
|
var lastSpaceSize = 1
|
||||||
|
var spaceSeq = false
|
||||||
|
|
||||||
|
def firstLine: Boolean = lines.isEmpty
|
||||||
|
|
||||||
|
def pushLine(line: String): Unit = {
|
||||||
|
lines += line
|
||||||
|
|
||||||
|
lastSpacePos = -1
|
||||||
|
lastSpaceSize = 1
|
||||||
|
lineWidth = 0
|
||||||
|
spaceSeq = false
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos + 1 < line.length) {
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
val (c, count) = if (pos + 1 < line.length && Character.isSurrogatePair(line(pos), line(pos + 1))) {
|
||||||
|
(Character.toCodePoint(line(pos), line(pos + 1)), 2)
|
||||||
|
} else (line(pos): Int, 1)
|
||||||
|
|
||||||
|
val isSpace = Character.isSpaceChar(c)
|
||||||
|
|
||||||
|
if (isSpace && pos == lineStart && !firstLine) {
|
||||||
|
// skip leading space
|
||||||
|
lineStart += count
|
||||||
|
} else {
|
||||||
|
if (!isSpace) {
|
||||||
|
spaceSeq = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSpace && !spaceSeq) {
|
||||||
|
lastSpacePos = pos
|
||||||
|
lastSpaceSize = count
|
||||||
|
spaceSeq = true
|
||||||
|
}
|
||||||
|
|
||||||
|
lineWidth += getWidth(c)
|
||||||
|
|
||||||
|
if (lineWidth > wrapWidth) {
|
||||||
|
if (lastSpacePos >= (pos - lineStart) / 2) {
|
||||||
|
val newLine = line.substring(lineStart, lastSpacePos)
|
||||||
|
|
||||||
|
// `+ lastSpaceSize` starts the line after the last whitespace character
|
||||||
|
// we set pos to the same position -- but before it gets there, it'll get incremented by `count`,
|
||||||
|
// so we do the subtraction
|
||||||
|
lineStart = lastSpacePos + lastSpaceSize
|
||||||
|
pos = lastSpacePos + lastSpaceSize - count
|
||||||
|
|
||||||
|
pushLine(newLine)
|
||||||
|
} else {
|
||||||
|
val newLine = line.substring(lineStart, pos)
|
||||||
|
lineStart = pos
|
||||||
|
pos -= 1
|
||||||
|
|
||||||
|
pushLine(newLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// subtract one, which we'll add back at the start of the next iteration
|
||||||
|
pos += count - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lineStart != pos + 1) {
|
||||||
|
pushLine(line.substring(lineStart))
|
||||||
|
}
|
||||||
|
|
||||||
|
lines
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package ocelot.desktop.ui.widget.card
|
||||||
|
|
||||||
|
import ocelot.desktop.geometry.{Padding2D, Size2D}
|
||||||
|
import ocelot.desktop.inventory.item.OcelotCardItem
|
||||||
|
import ocelot.desktop.ui.layout.{Layout, LinearLayout}
|
||||||
|
import ocelot.desktop.ui.widget.window.PanelWindow
|
||||||
|
import ocelot.desktop.ui.widget.{Button, Filler, LogWidget, PaddingBox, Widget}
|
||||||
|
import ocelot.desktop.util.Orientation
|
||||||
|
|
||||||
|
class OcelotCardWindow(item: OcelotCardItem) extends PanelWindow {
|
||||||
|
override protected def title: String = s"Ocelot card ${item.component.node.address}"
|
||||||
|
|
||||||
|
private val logWidget: LogWidget = new LogWidget {
|
||||||
|
override protected def messages: Iterable[String] = item.messages
|
||||||
|
override protected def textWidth: Int = 50
|
||||||
|
|
||||||
|
override def minimumSize: Size2D = super.minimumSize.copy(height = 300)
|
||||||
|
override def maximumSize: Size2D = minimumSize
|
||||||
|
}
|
||||||
|
|
||||||
|
setInner(new Widget {
|
||||||
|
override val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
||||||
|
|
||||||
|
children :+= logWidget
|
||||||
|
|
||||||
|
children :+= new PaddingBox(
|
||||||
|
new Widget {
|
||||||
|
children :+= new Filler
|
||||||
|
|
||||||
|
children :+= new Button {
|
||||||
|
override def text: String = "Clear"
|
||||||
|
override def onClick(): Unit = clear()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Padding2D(top = 4)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
private def clear(): Unit = {
|
||||||
|
item.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
def onMessagesAdded(count: Int): Unit = {
|
||||||
|
logWidget.onMessagesAdded(count)
|
||||||
|
}
|
||||||
|
|
||||||
|
def onMessagesCleared(): Unit = {
|
||||||
|
logWidget.onMessagesCleared()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user