1 from panda3d
.core
import NodePath
, Point2
, Point3
, Texture
, LVector3f
, LVector2f
, TextNode
2 from direct
.gui
.OnscreenText
import OnscreenText
3 from direct
.gui
.DirectGuiGlobals
import ENTER
, EXIT
4 from ya2
.utils
.decorator
import Decorator
10 def build_model(file_path
):
11 m
= loader
.load_model(file_path
)
12 m
= NodePathDecorator(m
) # we can't use mixins with c++ classes
16 def build_empty_node(name
):
17 return NodePathDecorator(NodePath(name
))
20 def build_node_from_physics(physics_node
):
21 return NodePathDecorator(render
.attach_new_node(physics_node
))
24 class NodePathDecorator(NodePath
, Decorator
):
26 def set_srgb_textures(self
):
27 for t
in self
.find_all_textures():
30 case Texture
.F_rgba | Texture
.F_rgbm
:
31 f
= Texture
.F_srgb_alpha
37 p3d
= base
.cam
.get_relative_point(self
, Point3(0, 0, 0))
39 return p2d
if base
.camLens
.project(p3d
, p2d
) else None
41 def pos2d_pixel(self
):
42 if p2d
:= self
.pos2d():
43 p
= _get_pos_relative((p2d
[0], 0, p2d
[1]), pixel2d
)
44 return int(round(p
[0])), int(round(-p
[2]))
46 def pos_as_widget(self
):
47 pos
= self
.get_pos(pixel2d
)
48 return int(round(pos
[0])), int(round(-pos
[2]))
51 class DirectGuiMixin():
53 registered_tooltips
= []
56 pos
= self
.get_pos(pixel2d
)
57 return int(round(pos
[0])), int(round(-pos
[2]))
59 def set_tooltip(self
, text
, font
, scale
, fg
, side
='left'):
60 self
.__tooltip
_txt
= text
61 self
.__tooltip
_font
= font
62 self
.__tooltip
_scale
= scale
63 self
.__tooltip
_fg
= fg
64 self
.bind(ENTER
, self
.__on
_enter
)
65 self
.bind(EXIT
, self
.__on
_exit
)
68 self
.__side
_delta
= (-.08, -.02)
69 self
.__align
= TextNode
.A_right
71 self
.__side
_delta
= (.08, -.02)
72 self
.__align
= TextNode
.A_left
74 def __on_enter(self
, mouse_pos
):
75 self
.__tooltip
_text
= OnscreenText(
77 pos
=(self
.get_pos()[0] + self
.__side
_delta
[0], self
.get_pos()[2] + self
.__side
_delta
[1]),
79 font
=self
.__tooltip
_font
,
80 scale
=self
.__tooltip
_scale
,
83 DirectGuiMixin
.registered_tooltips
+= [self
.__tooltip
_text
]
85 def __on_exit(self
, mouse_pos
):
86 self
.__tooltip
_text
.destroy()
90 # when we'll have proper gui classes with has-a containment
91 # remove this hack: the destroy will destroy the tooltip as well
92 for t
in DirectGuiMixin
.registered_tooltips
:
94 DirectGuiMixin
.registered_tooltips
= []
97 def pos_pixel(widget
):
98 pos
= widget
.get_pos(pixel2d
)
99 return int(round(pos
[0])), int(round(-pos
[2]))
102 class Point(Decorator
):
104 def screen_coord(self
):
105 pos3d
= _get_pos_relative(LVector3f(*self
), base
.cam
)
107 base
.camLens
.project(pos3d
, pos2d
)
108 pos_wrt_render2d
= Point3(pos2d
[0], 0, pos2d
[1])
109 pos_wrt_aspect2d
= base
.aspect2d
.get_relative_point(render2d
, pos_wrt_render2d
)
110 return Point((pos_wrt_aspect2d
[0], pos_wrt_aspect2d
[2]))
112 def from_to_points(self
):
113 p_from
, p_to
= Point3(), Point3() # in camera coordinates
114 base
.camLens
.extrude(LVector2f(*self
), p_from
, p_to
)
115 p_from
= render
.get_relative_point(base
.cam
, p_from
) # global coords
116 p_to
= render
.get_relative_point(base
.cam
, p_to
) # global coords
120 def _get_pos_relative(pos
, other
):
121 n
= NodePath('temporary_node')
123 pos
= n
.get_pos(other
)