Skip to content

Commit 33b1212

Browse files
committed
Added Asset manager and other improvements
shader loading wireframe toggle Fixed upside-down crosshair render and texture Crosshair negative over background updated crosshair image in atlas Color blend attribute presets
1 parent 0066840 commit 33b1212

File tree

8 files changed

+124
-44
lines changed

8 files changed

+124
-44
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ F3|Toggle visibility of debug view
5050
Shift+F3|Connect to Panda3D's PStats tool for profiling
5151
F5|Change camera mode from one of [Free, First Person or Third Person]
5252
F6|Toggle your control between camera and the Vehicle
53+
F8|Toggle wireframe render
5354
F11|Toggle fullscreen
5455
v|Show/hide all buffers
5556
`\`|Dump current simulator state to console

dronesim/app/asset_manager.py

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11

22
from direct.showbase.Loader import Loader
3-
from panda3d.core import FileStream, VirtualFileSystem
3+
from panda3d.core import (
4+
VirtualFileSystem,
5+
Filename,
6+
Shader
7+
)
48
from dronesim.types import PandaFilePath
59

610
import json
7-
from typing import Optional
11+
from typing import Optional, Callable, Dict, Any
812

913

1014
class VFSFileReaderMixin:
@@ -25,21 +29,51 @@ def read_file(cls, file_path: PandaFilePath, vfs: Optional[VirtualFileSystem] =
2529
with open(file_path, 'rb') as f:
2630
return f.read()
2731

32+
def read_json_file(assets_file: PandaFilePath, vfs: Optional[VirtualFileSystem] = None):
33+
asset_conf = AnyFileReaderMixin.read_file(assets_file, vfs)
34+
return json.loads(asset_conf)
2835

29-
class JSONLoader(AnyFileReaderMixin):
30-
@classmethod
31-
def load(cls, loader: Loader, assets_file: PandaFilePath, vfs: Optional[VirtualFileSystem] = None):
32-
# try:
33-
data = cls.read_file(assets_file, vfs)
34-
assets_config: dict = json.loads(data)
3536

37+
def loader_load_shader(cfg: dict, loader: Loader):
38+
shader_program_language = Shader.SL_GLSL
39+
vertex_path: Filename = Filename(cfg.get('vertex_path', ''))
40+
fragment_path: Filename = Filename(cfg.get('fragment_path', ''))
41+
geometry_path: Filename = Filename(cfg.get('geometry_path', ''))
42+
43+
shader_program = Shader.load(
44+
shader_program_language,
45+
vertex=vertex_path,
46+
fragment=fragment_path,
47+
geometry=geometry_path
48+
)
49+
50+
return shader_program
51+
52+
53+
ASSET_LOADERS: Dict[str, Callable[[dict, Loader], Any]] = {
54+
'shader': loader_load_shader
55+
}
56+
57+
class AssetHolder(dict):
58+
def __init__(selfs):
59+
super().__init__()
60+
61+
def load_from_config(self, assets_file: PandaFilePath, loader: Loader, vfs: Optional[VirtualFileSystem] = None):
62+
self.load(read_json_file(assets_file, vfs), loader, vfs)
63+
64+
def load(self, assets_config: dict, loader: Loader, vfs: Optional[VirtualFileSystem] = None):
3665
mounts: dict = assets_config.get('mounts', {})
66+
config_data: dict = assets_config.get('data', {})
3767
asset_load: dict = assets_config.get('load', {})
3868

39-
# TODO
69+
for asset_type, asset_items in asset_load.items():
70+
load_method = ASSET_LOADERS.get(asset_type)
71+
if load_method:
72+
for asset_name, asset_config in asset_items.items():
73+
is_enabled: bool = asset_config.pop('enabled', True)
74+
if is_enabled:
75+
asset = load_method(asset_config, loader)
76+
self[asset_name] = asset
4077

41-
# print("mounts:", mounts)
42-
# print("load:", asset_load)
4378

44-
# except OSError:
45-
# pass
79+
GLOBAL_ASSET_HOLDER = AssetHolder()

dronesim/app/attrib_presets.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
from panda3d.core import (
3+
LColor,
4+
ColorBlendAttrib
5+
)
6+
COLOR_BLEND_INVERT = ColorBlendAttrib.make(
7+
ColorBlendAttrib.M_subtract,
8+
ColorBlendAttrib.O_constant_color, ColorBlendAttrib.O_one,
9+
LColor(0.5,0.5,0.5,0)
10+
)
11+
12+
# COLOR_BLEND_INVERT = ColorBlendAttrib.make(
13+
# rgb_mode=ColorBlendAttrib.M_max,
14+
# rgb_a=ColorBlendAttrib.OOne,
15+
# rgb_b=ColorBlendAttrib.O_one_minus_incoming_color,
16+
17+
# alpha_mode = ColorBlendAttrib.M_max,
18+
# alpha_a=ColorBlendAttrib.OOne,
19+
# alpha_b=ColorBlendAttrib.O_one_minus_incoming_alpha
20+
# )

dronesim/app/hud.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from direct.gui.DirectGui import DirectFrame, OnscreenImage
1212
from typing import Optional, Tuple
1313

14+
from .attrib_presets import COLOR_BLEND_INVERT
15+
1416

1517
# TODO: Cleanup required
1618

@@ -28,18 +30,28 @@ def __init__(self, parent: Optional[NodePath] = None, **kwargs):
2830
super().__init__(parent=parent, **kwargs)
2931

3032
class Crosshair(NodePath):
31-
# Coord system is (left, right, bottom, top), and defines the bounds of the card
32-
FRAME_RANGE_DEFAULT = (-1,1,-1,1) # Same as using setFrameFullscreenQuad() on the CardMaker
33-
TEXTURE_UV_RANGE_DEFAULT = (LTexCoord(0,0), LTexCoord(1,-1))
33+
# Coord system of frame is (left, right, bottom, top), and defines the bounds of the card
34+
# Texture UV:
35+
# U = X-axis (0=left, 1=right)
36+
# V = Y-axis but from the bottom (1=bottom, 0=top)
37+
# So (0,1),(1,0) is the whole texture oriented from top-left to bottom-right.
38+
39+
TEXTURE_UV_RANGE_DEFAULT = (LTexCoord(0,1), LTexCoord(1,0))
3440
def __init__(self,
3541
name: str,
3642
tex: Texture,
37-
frame: Tuple[float,float,float,float] = FRAME_RANGE_DEFAULT,
43+
frame: Optional[Tuple[float,float,float,float]] = None,
3844
tex_uv_range: Tuple[LTexCoord,LTexCoord] = TEXTURE_UV_RANGE_DEFAULT):
3945
super().__init__(name)
4046
self._ch = CardMaker('cm_%s' % name)
41-
self._ch.set_frame(*frame)
47+
if frame is None:
48+
# Use the whole space (for aspect2d it will fill the window as a best-fit square)
49+
self._ch.setFrameFullscreenQuad()
50+
else:
51+
# Position and size from given bounds
52+
self._ch.set_frame(*frame)
4253
self._ch.set_uv_range(*tex_uv_range)
4354
self._ch_node = self.attach_new_node(self._ch.generate())
4455
self._ch_node.set_texture(tex)
45-
self._ch_node.set_transparency(TransparencyAttrib.MAlpha)
56+
self._ch_node.set_transparency(TransparencyAttrib.M_alpha)
57+
self._ch_node.set_attrib(COLOR_BLEND_INVERT)

dronesim/app/sim_app.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
Spotlight,
1212
LPoint3f, LVecBase3f, LPoint4f,
1313
NodePath, TextNode, SamplerState,
14-
LTexCoord,
14+
LColor, LTexCoord,
15+
RenderModeAttrib,
1516
PStatClient
1617
)
1718

@@ -29,7 +30,7 @@
2930
from .hud import HUDFieldMixin, HUDFrame, Crosshair
3031
from .environment import Panda3DEnvironment
3132
from .camera_control import FreeCam, FPCamera, TPCamera
32-
from .asset_manager import JSONLoader
33+
from .asset_manager import GLOBAL_ASSET_HOLDER
3334

3435
from dronesim.actor import VehicleModel
3536

@@ -56,18 +57,7 @@
5657
"""
5758
loadPrcFileData("", DEFAULT_CONFIG_VARS)
5859

59-
# Instruct the Virtual File System to mount the real 'assets/' folder to the virtual directory '/assets/'
6060
ASSETS_VFS = VirtualFileSystem.get_global_ptr()
61-
ASSETS_VFS.mount(
62-
VirtualFileMountSystem(Filename.from_os_specific(
63-
os.path.join(PACKAGE_BASE, 'assets/')
64-
)),
65-
'/assets/',
66-
VirtualFileSystem.MFReadOnly
67-
)
68-
69-
# Add virtual assets directory to load models and scenes from to the loader's search path
70-
getModelPath().prepend_directory('/assets')
7161

7262
# Colors used for some HUD elements as foreground (text color) and background
7363
HUD_COLORS = dict(
@@ -78,6 +68,23 @@
7868
LOG = logging.getLogger(__name__)
7969

8070

71+
def mount_assets_folder(vfs: VirtualFileSystem = ASSETS_VFS):
72+
'''
73+
Instruct the Virtual File System to mount the real `assets/` folder to the virtual directory `/assets/`
74+
'''
75+
vfs.mount(
76+
VirtualFileMountSystem(Filename.from_os_specific(
77+
os.path.join(PACKAGE_BASE, 'assets/')
78+
)),
79+
'/assets/',
80+
VirtualFileSystem.MFReadOnly
81+
)
82+
83+
# Add virtual assets directory to load models and scenes from to the loader's search path
84+
getModelPath().prepend_directory('/assets')
85+
86+
mount_assets_folder()
87+
8188
def objectHUDFormatter(o):
8289
'''Simple JSON string formatter for various data types'''
8390
if isinstance(o, enum.Enum):
@@ -315,6 +322,12 @@ def eToggleDebugView(self):
315322
else:
316323
self.HUD_debug_info.hide()
317324

325+
def eToggleWireframe(self):
326+
if self.render.getRenderMode() == RenderModeAttrib.M_unchanged:
327+
self.render.setRenderModeFilledWireframe(LColor(0,1,0,1))
328+
else:
329+
self.render.clearRenderMode()
330+
318331
def eConnectPStats(self):
319332
'''Start connection with Pandas' PStats server, or disconnects from it'''
320333
self._toggle_pstats_connection()
@@ -427,9 +440,7 @@ def _getMovementControlState(self) -> StepRC:
427440
# App/UI related
428441

429442
def _init_assets(self):
430-
assets = JSONLoader.load(
431-
self.loader, self._assets_load_file, ASSETS_VFS)
432-
# TODO
443+
GLOBAL_ASSET_HOLDER.load_from_config(self._assets_load_file, self.loader, ASSETS_VFS)
433444

434445
def _init_keybinds(self):
435446
# Buffer viewer keybind
@@ -444,6 +455,7 @@ def _init_keybinds(self):
444455
self._event_hook.accept("shift-wheel_down", self.eMouseWheelScroll, [-0.25])
445456
self._event_hook.accept("f1", self.eToggleHUDView)
446457
self._event_hook.accept("f3", self.eToggleDebugView)
458+
self._event_hook.accept("f8", self.eToggleWireframe)
447459
self._event_hook.accept("shift-f3", self.eConnectPStats)
448460
self._event_hook.accept("f5", self.eToggleCameraMode)
449461
self._event_hook.accept("f6", self.eToggleControlMode)
@@ -493,8 +505,8 @@ def _init_hud(self):
493505
self.HUD_crosshair = Crosshair(
494506
"player_crosshair",
495507
crosshair_tex,
496-
frame=square_aspect2d_frame(0.015),
497-
tex_uv_range=(LTexCoord(4/128,-4/128),LTexCoord(12/128,-12/128))
508+
frame=square_aspect2d_frame(0.02),
509+
tex_uv_range=(LTexCoord(4/128, 1 - (11/128)), LTexCoord(11/128, 1 - (4/128)))
498510
)
499511
self.HUD_crosshair.reparent_to(self.HUD_holder)
500512

@@ -525,10 +537,11 @@ def _init_ui(self):
525537

526538
@classmethod
527539
def formatDictToHUD(cls, d: dict, serializer: Callable[[Any], str] = str, level=0) -> str:
540+
INDENT = ' '
528541
return '\n'.join(
529542
'%s%s:\n%s' % (
530-
' '*level, k, cls.formatDictToHUD(v, serializer, level+1))
543+
INDENT*level, k, cls.formatDictToHUD(v, serializer, level+1))
531544
if isinstance(v, dict)
532-
else (' '*level+k+': '+serializer(v))
545+
else ('%s%s: %s' % (INDENT*level, k, serializer(v)))
533546
for k, v in d.items()
534547
)

dronesim/assets/assets.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@
2525
"tex.ui.atlas1": {
2626
"path": "/assets/textures/ui_1.png",
2727
"options": {
28-
"minfilter": "{SamplerState.FT_nearest}",
29-
"magfilter": "{SamplerState.FT_nearest}"
28+
"minfilter": "{p3dc.SamplerState.FT_nearest}",
29+
"magfilter": "{p3dc.SamplerState.FT_nearest}"
3030
},
3131
"data": {
3232
"hud": {
3333
"crosshair": {
3434
"uv_range": [
35-
[0.03125, -0.03125],
36-
[0.09375, -0.09375]
35+
[0.03125, 0.90625],
36+
[0.09375, 0.96875]
3737
]
3838
}
3939
}
@@ -56,7 +56,7 @@
5656

5757
},
5858
"shader": {
59-
59+
6060
}
6161
}
6262
}

dronesim/assets/textures/ui_1.png

-31 Bytes
Loading

dronesim/shader/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)