mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 08:15:18 -04:00
rocket: Add sample showing some Panda3D uses of libRocket. (#24)
This commit is contained in:
parent
0493b07f45
commit
34731cd2f4
BIN
samples/rocket-console/assets/Perfect DOS VGA 437.ttf
Normal file
BIN
samples/rocket-console/assets/Perfect DOS VGA 437.ttf
Normal file
Binary file not shown.
38
samples/rocket-console/assets/console.rcss
Executable file
38
samples/rocket-console/assets/console.rcss
Executable file
@ -0,0 +1,38 @@
|
||||
body
|
||||
{
|
||||
font-family: "Perfect DOS VGA 437";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
// use all the allocated texture space
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
|
||||
text#content
|
||||
{
|
||||
z-index: 2;
|
||||
font-size: 30px;
|
||||
|
||||
white-space: pre-wrap;
|
||||
|
||||
margin: auto;
|
||||
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
|
||||
// account for non-proportionality of our 1024x512
|
||||
// buffer compared with VGA font proportions and
|
||||
// wanting to center the screen with 40 columns
|
||||
top: 16px;
|
||||
left: 32px;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
color: #888;
|
||||
|
||||
}
|
11
samples/rocket-console/assets/console.rml
Executable file
11
samples/rocket-console/assets/console.rml
Executable file
@ -0,0 +1,11 @@
|
||||
<rml>
|
||||
|
||||
<head>
|
||||
<title>Administrative Console</title>
|
||||
<link type="text/rcss" href="console.rcss"/>
|
||||
</head>
|
||||
<!-- events are bound strictly from code -->
|
||||
<body >
|
||||
<text id="content" />
|
||||
</body>
|
||||
</rml>
|
1
samples/rocket-console/assets/dos437.txt
Normal file
1
samples/rocket-console/assets/dos437.txt
Normal file
@ -0,0 +1 @@
|
||||
from www.dafont.com/perfect-dos-vga-437.font (info at http://zehfernando.com/2015/revisiting-vga-fonts/)
|
54
samples/rocket-console/assets/loading.rml
Executable file
54
samples/rocket-console/assets/loading.rml
Executable file
@ -0,0 +1,54 @@
|
||||
<rml>
|
||||
<head >
|
||||
<title>Main Menu</title>
|
||||
<link type="text/template" href="window.rml" />
|
||||
<style>
|
||||
body
|
||||
{
|
||||
width: 400px;
|
||||
height: 225px;
|
||||
|
||||
margin: auto;
|
||||
|
||||
background-color: #44f;
|
||||
}
|
||||
|
||||
|
||||
div#title_bar_content
|
||||
{
|
||||
font-size: 48;
|
||||
|
||||
//text-align: left;
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
//vertical-align: center;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
import _rocketcore as rocket
|
||||
|
||||
# This handler overrides the 'onkeydown' handler from the template
|
||||
def OnKeyDown(event, document):
|
||||
keyId = event.parameters['key_identifier']
|
||||
if keyId in [ rocket.key_identifier.RETURN,
|
||||
rocket.key_identifier.ESCAPE,
|
||||
rocket.key_identifier.SPACE ]:
|
||||
FireClosing(document)
|
||||
|
||||
# custom event
|
||||
def FireClosing(document):
|
||||
document.DispatchEvent("aboutToClose", { }, False)
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body id='window' template="window" onclick='FireClosing(document)'>
|
||||
<div id="title_bar_content" >
|
||||
<label id="loadingLabel">Loading...</label>
|
||||
</div>
|
||||
</body>
|
||||
</rml>
|
18
samples/rocket-console/assets/modenine.nfo
Normal file
18
samples/rocket-console/assets/modenine.nfo
Normal file
@ -0,0 +1,18 @@
|
||||
ModeNine
|
||||
|
||||
Based on Andrew Bulhak's ModeSeven, in turn inspired by the screen
|
||||
output of the BBC Micro.
|
||||
|
||||
copyright:
|
||||
(C) 1998 Andrew C. Bulhak
|
||||
(C) 2001 Graham H Freeman
|
||||
|
||||
Freely Distributable.
|
||||
|
||||
All we ask is that this readme file must be included with the font package.
|
||||
Impresarios of free font sites and shovelware cd-roms, this means you!
|
||||
|
||||
If you think this font is doovy, let us know at fonts@grudnuk.com, and we
|
||||
might actually make more fonts.
|
||||
|
||||
Another fine Grudnuk Creations produkt | http://grudnuk.com/
|
BIN
samples/rocket-console/assets/modenine.ttf
Normal file
BIN
samples/rocket-console/assets/modenine.ttf
Normal file
Binary file not shown.
BIN
samples/rocket-console/assets/monitor.egg.pz
Normal file
BIN
samples/rocket-console/assets/monitor.egg.pz
Normal file
Binary file not shown.
12
samples/rocket-console/assets/monitor.txt
Normal file
12
samples/rocket-console/assets/monitor.txt
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
This is an edited version of this file from blendswap.com (http://www.blendswap.com/blends/view/74468).
|
||||
|
||||
VERY IMPORTANT LICENSE INFORMATION:
|
||||
|
||||
This file has been released by buzo under the following license:
|
||||
|
||||
Creative Commons Zero (Public Domain)
|
||||
|
||||
You can use this model for any purposes according to the following conditions:
|
||||
|
||||
There are no requirements for CC-Zero licensed blends.
|
44
samples/rocket-console/assets/rkt.rcss
Executable file
44
samples/rocket-console/assets/rkt.rcss
Executable file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Default styles for all the basic elements.
|
||||
*/
|
||||
|
||||
div
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
em
|
||||
{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
strong
|
||||
{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
datagrid
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
select, dataselect, datacombo
|
||||
{
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
tabset tabs
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
316
samples/rocket-console/assets/takeyga_kb.egg
Normal file
316
samples/rocket-console/assets/takeyga_kb.egg
Normal file
@ -0,0 +1,316 @@
|
||||
<CoordinateSystem> { Z-up }
|
||||
<Material> takeyga_kb {
|
||||
<Scalar> diffr { 0.800000 }
|
||||
<Scalar> diffg { 0.800000 }
|
||||
<Scalar> diffb { 0.800000 }
|
||||
<Scalar> specr { 0.500000 }
|
||||
<Scalar> specg { 0.500000 }
|
||||
<Scalar> specb { 0.500000 }
|
||||
<Scalar> shininess { 12.5 }
|
||||
<Scalar> ambr { 1.000000 }
|
||||
<Scalar> ambg { 1.000000 }
|
||||
<Scalar> ambb { 1.000000 }
|
||||
<Scalar> emitr { 0.000000 }
|
||||
<Scalar> emitg { 0.000000 }
|
||||
<Scalar> emitb { 0.000000 }
|
||||
}
|
||||
|
||||
<Texture> Texture.001 {
|
||||
"./tex/takeyga_kb_specular.dds"
|
||||
<Scalar> envtype { MODULATE }
|
||||
<Scalar> minfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> magfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> wrap { REPEAT }
|
||||
}
|
||||
|
||||
<Texture> Tex {
|
||||
"./tex/takeyga_kb_diffuse.dds"
|
||||
<Scalar> envtype { MODULATE }
|
||||
<Scalar> minfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> magfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> wrap { REPEAT }
|
||||
}
|
||||
|
||||
<Texture> Texture {
|
||||
"./tex/takeyga_kb_normal.dds"
|
||||
<Scalar> envtype { NORMAL }
|
||||
<Scalar> minfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> magfilter { LINEAR_MIPMAP_LINEAR }
|
||||
<Scalar> wrap { REPEAT }
|
||||
}
|
||||
|
||||
<Group> Cube.001 {
|
||||
<Transform> {
|
||||
<Matrix4> {
|
||||
0.08499996364116669 0.0 0.0 0.0
|
||||
0.0 0.23999987542629242 0.0 0.0
|
||||
0.0 0.0 0.02500000037252903 0.0
|
||||
0.0 0.0 0.0 1.0
|
||||
}
|
||||
}
|
||||
|
||||
<VertexPool> Cube.001 {
|
||||
|
||||
<Vertex> 0 {0.082953 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.158203125 0.595703125
|
||||
}
|
||||
}
|
||||
<Vertex> 1 {0.082953 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.98828125 0.6015625
|
||||
}
|
||||
}
|
||||
<Vertex> 2 {-0.085000 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.98828125 0.986328125
|
||||
}
|
||||
}
|
||||
<Vertex> 3 {-0.085000 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.162109375 0.98828125
|
||||
}
|
||||
}
|
||||
<Vertex> 4 {0.073544 0.227744 -0.005546
|
||||
<UV> {
|
||||
0.990234375 0.017578125
|
||||
}
|
||||
}
|
||||
<Vertex> 5 {-0.067932 0.223167 0.018996
|
||||
<UV> {
|
||||
0.98046875 0.46875
|
||||
}
|
||||
}
|
||||
<Vertex> 6 {-0.067932 -0.223167 0.018996
|
||||
<UV> {
|
||||
0.017578125 0.470703125
|
||||
}
|
||||
}
|
||||
<Vertex> 7 {0.073544 -0.227744 -0.005546
|
||||
<UV> {
|
||||
0.01953125 0.013671875
|
||||
}
|
||||
}
|
||||
<Vertex> 8 {0.082372 0.237328 -0.015273
|
||||
<UV> {
|
||||
0.9794921875 0.552734375
|
||||
}
|
||||
}
|
||||
<Vertex> 9 {0.073544 0.227744 -0.005546
|
||||
<UV> {
|
||||
0.9765625 0.57421875
|
||||
}
|
||||
}
|
||||
<Vertex> 10 {0.073544 -0.227744 -0.005546
|
||||
<UV> {
|
||||
0.025390625 0.57421875
|
||||
}
|
||||
}
|
||||
<Vertex> 11 {0.082372 -0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0234375 0.5537109375
|
||||
}
|
||||
}
|
||||
<Vertex> 12 {0.082372 -0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0703125 0.6123046875
|
||||
}
|
||||
}
|
||||
<Vertex> 13 {0.073544 -0.227744 -0.005546
|
||||
<UV> {
|
||||
0.095703125 0.615234375
|
||||
}
|
||||
}
|
||||
<Vertex> 14 {-0.067932 -0.223167 0.018996
|
||||
<UV> {
|
||||
0.13671875 0.97265625
|
||||
}
|
||||
}
|
||||
<Vertex> 15 {-0.080884 -0.235006 0.001122
|
||||
<UV> {
|
||||
0.07421875 0.982421875
|
||||
}
|
||||
}
|
||||
<Vertex> 16 {-0.080884 -0.235006 0.001122
|
||||
<UV> {
|
||||
0.0166015625 0.5361328125
|
||||
}
|
||||
}
|
||||
<Vertex> 17 {-0.067932 -0.223167 0.018996
|
||||
<UV> {
|
||||
0.017578125 0.58203125
|
||||
}
|
||||
}
|
||||
<Vertex> 18 {-0.067932 0.223167 0.018996
|
||||
<UV> {
|
||||
0.978515625 0.580078125
|
||||
}
|
||||
}
|
||||
<Vertex> 19 {-0.080884 0.235006 0.001122
|
||||
<UV> {
|
||||
0.984375 0.5341796875
|
||||
}
|
||||
}
|
||||
<Vertex> 20 {0.082372 0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0703125 0.6123046875
|
||||
}
|
||||
}
|
||||
<Vertex> 21 {0.082953 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.044921875 0.609375
|
||||
}
|
||||
}
|
||||
<Vertex> 22 {-0.085000 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.01171875 0.9921875
|
||||
}
|
||||
}
|
||||
<Vertex> 23 {-0.080884 0.235006 0.001122
|
||||
<UV> {
|
||||
0.07421875 0.982421875
|
||||
}
|
||||
}
|
||||
<Vertex> 24 {0.082953 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.982421875 0.53125
|
||||
}
|
||||
}
|
||||
<Vertex> 25 {0.082372 0.237328 -0.015273
|
||||
<UV> {
|
||||
0.9794921875 0.552734375
|
||||
}
|
||||
}
|
||||
<Vertex> 26 {0.082372 -0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0234375 0.5537109375
|
||||
}
|
||||
}
|
||||
<Vertex> 27 {0.082953 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.021484375 0.533203125
|
||||
}
|
||||
}
|
||||
<Vertex> 28 {0.082953 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.044921875 0.609375
|
||||
}
|
||||
}
|
||||
<Vertex> 29 {0.082372 -0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0703125 0.6123046875
|
||||
}
|
||||
}
|
||||
<Vertex> 30 {-0.080884 -0.235006 0.001122
|
||||
<UV> {
|
||||
0.07421875 0.982421875
|
||||
}
|
||||
}
|
||||
<Vertex> 31 {-0.085000 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.01171875 0.9921875
|
||||
}
|
||||
}
|
||||
<Vertex> 32 {-0.085000 -0.240000 -0.025000
|
||||
<UV> {
|
||||
0.015625 0.490234375
|
||||
}
|
||||
}
|
||||
<Vertex> 33 {-0.080884 -0.235006 0.001122
|
||||
<UV> {
|
||||
0.0166015625 0.5361328125
|
||||
}
|
||||
}
|
||||
<Vertex> 34 {-0.080884 0.235006 0.001122
|
||||
<UV> {
|
||||
0.984375 0.5341796875
|
||||
}
|
||||
}
|
||||
<Vertex> 35 {-0.085000 0.240000 -0.025000
|
||||
<UV> {
|
||||
0.990234375 0.48828125
|
||||
}
|
||||
}
|
||||
<Vertex> 36 {0.073544 0.227744 -0.005546
|
||||
<UV> {
|
||||
0.095703125 0.615234375
|
||||
}
|
||||
}
|
||||
<Vertex> 37 {0.082372 0.237328 -0.015273
|
||||
<UV> {
|
||||
0.0703125 0.6123046875
|
||||
}
|
||||
}
|
||||
<Vertex> 38 {-0.080884 0.235006 0.001122
|
||||
<UV> {
|
||||
0.07421875 0.982421875
|
||||
}
|
||||
}
|
||||
<Vertex> 39 {-0.067932 0.223167 0.018996
|
||||
<UV> {
|
||||
0.13671875 0.97265625
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.000000 0.000000 -1.000000}
|
||||
<VertexRef> { 0 1 2 3 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.508027 -0.000000 0.861341}
|
||||
<VertexRef> { 4 5 6 7 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.966167 -0.000000 0.257917}
|
||||
<VertexRef> { 8 9 10 11 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.028240 -0.996449 0.079322}
|
||||
<VertexRef> { 12 13 14 15 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {-0.978036 0.000000 0.208436}
|
||||
<VertexRef> { 16 17 18 19 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.001260 0.999752 0.022233}
|
||||
<VertexRef> { 20 21 22 23 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.999846 -0.000000 0.017550}
|
||||
<VertexRef> { 24 25 26 27 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.001259 -0.999752 0.022233}
|
||||
<VertexRef> { 28 29 30 31 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {-0.998928 0.000000 0.046291}
|
||||
<VertexRef> { 32 33 34 35 <Ref> { Cube.001 }}
|
||||
}
|
||||
<Polygon> {
|
||||
<TRef> { Tex }
|
||||
<MRef> { takeyga_kb }
|
||||
<Normal> {0.028241 0.996449 0.079322}
|
||||
<VertexRef> { 36 37 38 39 <Ref> { Cube.001 }}
|
||||
}
|
||||
}
|
BIN
samples/rocket-console/assets/tex/takeyga_kb_diffuse.dds
Normal file
BIN
samples/rocket-console/assets/tex/takeyga_kb_diffuse.dds
Normal file
Binary file not shown.
BIN
samples/rocket-console/assets/tex/takeyga_kb_normal.dds
Normal file
BIN
samples/rocket-console/assets/tex/takeyga_kb_normal.dds
Normal file
Binary file not shown.
BIN
samples/rocket-console/assets/tex/takeyga_kb_specular.dds
Normal file
BIN
samples/rocket-console/assets/tex/takeyga_kb_specular.dds
Normal file
Binary file not shown.
56
samples/rocket-console/assets/window.rcss
Executable file
56
samples/rocket-console/assets/window.rcss
Executable file
@ -0,0 +1,56 @@
|
||||
body
|
||||
{
|
||||
font-family: "MODENINE";
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 15;
|
||||
|
||||
}
|
||||
|
||||
body.window
|
||||
{
|
||||
padding-top: 43px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
min-width: 250px;
|
||||
|
||||
min-height: 135px;
|
||||
max-height: 700px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
div#title_bar
|
||||
{
|
||||
z-index: 1;
|
||||
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #fff;
|
||||
background-color: #22f;
|
||||
}
|
||||
|
||||
|
||||
div#title_bar span
|
||||
{
|
||||
padding-top: 17px;
|
||||
padding-bottom: 48px;
|
||||
|
||||
font-size: 32;
|
||||
font-weight: bold;
|
||||
|
||||
outline-font-effect: outline;
|
||||
outline-width: 1px;
|
||||
outline-color: black;
|
||||
}
|
||||
|
||||
div#title_bar_content
|
||||
{
|
||||
text-align: center;
|
||||
color: #cff;
|
||||
}
|
42
samples/rocket-console/assets/window.rml
Executable file
42
samples/rocket-console/assets/window.rml
Executable file
@ -0,0 +1,42 @@
|
||||
<template name="window" content="content">
|
||||
<head>
|
||||
<link type="text/rcss" href="rkt.rcss"/>
|
||||
<link type="text/rcss" href="window.rcss"/>
|
||||
|
||||
|
||||
<script>
|
||||
import _rocketcore as rocket
|
||||
|
||||
def OnLoad(document):
|
||||
print "Rocket document loaded"
|
||||
|
||||
# event handlers from templates can be overridden in windows using them
|
||||
def OnKeyDown(event, document):
|
||||
keyId = event.parameters['key_identifier']
|
||||
print "Base keydown: unhandled key ",keyId
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
||||
<body class="window" onload='OnLoad(document)' onkeydown='OnKeyDown(event, document)'>
|
||||
<div id="title_bar">
|
||||
<handle move_target="#document">
|
||||
<span id="title">Rocket Sample</span>
|
||||
|
||||
<div id="title_bar_content">
|
||||
</div>
|
||||
</handle>
|
||||
</div>
|
||||
<div id="window">
|
||||
<div id="content">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- drag and drop of window -->
|
||||
<handle size_target="#document"
|
||||
style="position: absolute; width: 16px; height: 16px; bottom: 0px; right: 0px;">
|
||||
</handle>
|
||||
</body>
|
||||
|
||||
</template>
|
153
samples/rocket-console/console.py
Normal file
153
samples/rocket-console/console.py
Normal file
@ -0,0 +1,153 @@
|
||||
"""
|
||||
Simple console widget for rocket
|
||||
"""
|
||||
import sys, os.path
|
||||
|
||||
# workaround: https://www.panda3d.org/forums/viewtopic.php?t=10062&p=99697#p99054
|
||||
#from panda3d import rocket
|
||||
import _rocketcore as rocket
|
||||
|
||||
from panda3d.rocket import RocketRegion, RocketInputHandler
|
||||
|
||||
class Console(object):
|
||||
def __init__(self, base, context, cols, rows, commandHandler):
|
||||
self.base = base
|
||||
|
||||
self.context = context
|
||||
self.loadFonts()
|
||||
self.cols = cols
|
||||
self.rows = rows
|
||||
self.commandHandler = commandHandler
|
||||
|
||||
self.setupConsole()
|
||||
self.allowEditing(True)
|
||||
|
||||
def getTextContainer(self):
|
||||
return self.textEl
|
||||
|
||||
def setPrompt(self, prompt):
|
||||
self.consolePrompt = prompt
|
||||
|
||||
def allowEditing(self, editMode):
|
||||
self.editMode = editMode
|
||||
if editMode:
|
||||
self.input = ""
|
||||
if not self.lastLine:
|
||||
self.addLine("")
|
||||
self.newEditLine()
|
||||
|
||||
def loadFonts(self):
|
||||
rocket.LoadFontFace("Perfect DOS VGA 437.ttf")
|
||||
|
||||
def setupConsole(self):
|
||||
self.document = self.context.LoadDocument("console.rml")
|
||||
if not self.document:
|
||||
raise AssertionError("did not find console.rml")
|
||||
|
||||
el = self.document.GetElementById('content')
|
||||
|
||||
self.textEl = el
|
||||
|
||||
# roundabout way of accessing the current object through rocket event...
|
||||
|
||||
# add attribute to let Rocket know about the receiver
|
||||
self.context.console = self
|
||||
|
||||
# then reference through the string format (dunno how else to get the event...)
|
||||
self.document.AddEventListener(
|
||||
'keydown', 'document.context.console.handleKeyDown(event)', True)
|
||||
self.document.AddEventListener(
|
||||
'textinput', 'document.context.console.handleTextInput(event)', True)
|
||||
|
||||
self.consolePrompt = "C:\\>"
|
||||
|
||||
self.input = ""
|
||||
self.lastLine = None
|
||||
|
||||
self.blinkState = False
|
||||
self.queueBlinkCursor()
|
||||
|
||||
self.document.Show()
|
||||
|
||||
def queueBlinkCursor(self):
|
||||
self.base.taskMgr.doMethodLater(0.2, self.blinkCursor, 'blinkCursor')
|
||||
|
||||
def blinkCursor(self, task):
|
||||
self.blinkState = not self.blinkState
|
||||
if self.editMode:
|
||||
self.updateEditLine(self.input)
|
||||
self.queueBlinkCursor()
|
||||
|
||||
def escape(self, text):
|
||||
return text. \
|
||||
replace('<', '<'). \
|
||||
replace('>', '>'). \
|
||||
replace('"', '"')
|
||||
|
||||
def addLine(self, text):
|
||||
curKids = list(self.textEl.child_nodes)
|
||||
while len(curKids) >= self.rows:
|
||||
self.textEl.RemoveChild(curKids[0])
|
||||
curKids = curKids[1:]
|
||||
|
||||
line = self.document.CreateTextNode(self.escape(text) + '\n')
|
||||
self.textEl.AppendChild(line)
|
||||
self.lastLine = line
|
||||
|
||||
def addLines(self, lines):
|
||||
for line in lines:
|
||||
self.addLine(line)
|
||||
|
||||
def updateEditLine(self, newInput=''):
|
||||
newText = self.consolePrompt + newInput
|
||||
self.lastLine.text = self.escape(newText) + (self.blinkState and '_' or '')
|
||||
self.input = newInput
|
||||
|
||||
def scroll(self):
|
||||
self.blinkState = False
|
||||
self.updateEditLine(self.input + '\n')
|
||||
|
||||
def handleKeyDown(self, event):
|
||||
"""
|
||||
Handle control keys
|
||||
"""
|
||||
keyId = event.parameters['key_identifier']
|
||||
if not self.editMode:
|
||||
if keyId == rocket.key_identifier.PAUSE:
|
||||
if event.parameters['ctrl_key']:
|
||||
self.commandHandler(None)
|
||||
|
||||
return
|
||||
|
||||
if keyId == rocket.key_identifier.RETURN:
|
||||
# emit line without cursor
|
||||
self.scroll()
|
||||
|
||||
# handle command
|
||||
self.commandHandler(self.input)
|
||||
|
||||
if self.editMode:
|
||||
# start with new "command"
|
||||
self.addLine(self.consolePrompt)
|
||||
self.updateEditLine("")
|
||||
|
||||
elif keyId == rocket.key_identifier.BACK:
|
||||
self.updateEditLine(self.input[0:-1])
|
||||
|
||||
def handleTextInput(self, event):
|
||||
if not self.editMode:
|
||||
return
|
||||
|
||||
# handle normal text character
|
||||
data = event.parameters['data']
|
||||
if 32 <= data < 128:
|
||||
self.updateEditLine(self.input + chr(data))
|
||||
|
||||
def newEditLine(self):
|
||||
self.addLine("")
|
||||
self.updateEditLine()
|
||||
|
||||
def cls(self):
|
||||
curKids = list(self.textEl.child_nodes)
|
||||
for kid in curKids:
|
||||
self.textEl.RemoveChild(kid)
|
410
samples/rocket-console/main.py
Normal file
410
samples/rocket-console/main.py
Normal file
@ -0,0 +1,410 @@
|
||||
"""
|
||||
Show how to use libRocket in Panda3D.
|
||||
"""
|
||||
import sys
|
||||
from panda3d.core import loadPrcFile, loadPrcFileData, Point3,Vec4, Mat4, LoaderOptions # @UnusedImport
|
||||
from panda3d.core import DirectionalLight, AmbientLight, PointLight
|
||||
from panda3d.core import Texture, PNMImage
|
||||
from panda3d.core import PandaSystem
|
||||
import random
|
||||
from direct.interval.LerpInterval import LerpHprInterval, LerpPosInterval, LerpFunc
|
||||
from direct.showbase.ShowBase import ShowBase
|
||||
|
||||
# workaround: https://www.panda3d.org/forums/viewtopic.php?t=10062&p=99697#p99054
|
||||
#from panda3d import rocket
|
||||
import _rocketcore as rocket
|
||||
|
||||
from panda3d.rocket import RocketRegion, RocketInputHandler
|
||||
|
||||
loadPrcFileData("", "model-path $MAIN_DIR/assets")
|
||||
|
||||
import console
|
||||
|
||||
global globalClock
|
||||
|
||||
class MyApp(ShowBase):
|
||||
|
||||
def __init__(self):
|
||||
ShowBase.__init__(self)
|
||||
|
||||
self.win.setClearColor(Vec4(0.2, 0.2, 0.2, 1))
|
||||
|
||||
self.disableMouse()
|
||||
|
||||
self.render.setShaderAuto()
|
||||
|
||||
dlight = DirectionalLight('dlight')
|
||||
alight = AmbientLight('alight')
|
||||
dlnp = self.render.attachNewNode(dlight)
|
||||
alnp = self.render.attachNewNode(alight)
|
||||
dlight.setColor((0.8, 0.8, 0.5, 1))
|
||||
alight.setColor((0.2, 0.2, 0.2, 1))
|
||||
dlnp.setHpr(0, -60, 0)
|
||||
self.render.setLight(dlnp)
|
||||
self.render.setLight(alnp)
|
||||
|
||||
# Put lighting on the main scene
|
||||
plight = PointLight('plight')
|
||||
plnp = self.render.attachNewNode(plight)
|
||||
plnp.setPos(0, 0, 10)
|
||||
self.render.setLight(plnp)
|
||||
self.render.setLight(alnp)
|
||||
|
||||
self.loadRocketFonts()
|
||||
|
||||
self.loadingTask = None
|
||||
|
||||
#self.startModelLoadingAsync()
|
||||
self.startModelLoading()
|
||||
|
||||
self.inputHandler = RocketInputHandler()
|
||||
self.mouseWatcher.attachNewNode(self.inputHandler)
|
||||
|
||||
self.openLoadingDialog()
|
||||
|
||||
def loadRocketFonts(self):
|
||||
""" Load fonts referenced from e.g. 'font-family' RCSS directives.
|
||||
|
||||
Note: the name of the font as used in 'font-family'
|
||||
is not always the same as the filename;
|
||||
open the font in your OS to see its display name.
|
||||
"""
|
||||
rocket.LoadFontFace("modenine.ttf")
|
||||
|
||||
|
||||
def startModelLoading(self):
|
||||
self.monitorNP = None
|
||||
self.keyboardNP = None
|
||||
self.loadingError = False
|
||||
|
||||
self.taskMgr.doMethodLater(1, self.loadModels, 'loadModels')
|
||||
|
||||
def loadModels(self, task):
|
||||
self.monitorNP = self.loader.loadModel("monitor")
|
||||
self.keyboardNP = self.loader.loadModel("takeyga_kb")
|
||||
|
||||
def startModelLoadingAsync(self):
|
||||
"""
|
||||
NOTE: this seems to invoke a few bugs (crashes, sporadic model
|
||||
reading errors, etc) so is disabled for now...
|
||||
"""
|
||||
self.monitorNP = None
|
||||
self.keyboardNP = None
|
||||
self.loadingError = False
|
||||
|
||||
# force the "loading" to take some time after the first run...
|
||||
options = LoaderOptions()
|
||||
options.setFlags(options.getFlags() | LoaderOptions.LFNoCache)
|
||||
|
||||
def gotMonitorModel(model):
|
||||
if not model:
|
||||
self.loadingError = True
|
||||
self.monitorNP = model
|
||||
|
||||
self.loader.loadModel("monitor", loaderOptions=options, callback=gotMonitorModel)
|
||||
|
||||
def gotKeyboardModel(model):
|
||||
if not model:
|
||||
self.loadingError = True
|
||||
self.keyboardNP = model
|
||||
|
||||
self.loader.loadModel("takeyga_kb", loaderOptions=options, callback=gotKeyboardModel)
|
||||
|
||||
def openLoadingDialog(self):
|
||||
self.userConfirmed = False
|
||||
|
||||
self.windowRocketRegion = RocketRegion.make('pandaRocket', self.win)
|
||||
self.windowRocketRegion.setActive(1)
|
||||
|
||||
self.windowRocketRegion.setInputHandler(self.inputHandler)
|
||||
|
||||
self.windowContext = self.windowRocketRegion.getContext()
|
||||
|
||||
self.loadingDocument = self.windowContext.LoadDocument("loading.rml")
|
||||
if not self.loadingDocument:
|
||||
raise AssertionError("did not find loading.rml")
|
||||
|
||||
self.loadingDots = 0
|
||||
el = self.loadingDocument.GetElementById('loadingLabel')
|
||||
self.loadingText = el.first_child
|
||||
self.stopLoadingTime = globalClock.getFrameTime() + 3
|
||||
self.loadingTask = self.taskMgr.add(self.cycleLoading, 'doc changer')
|
||||
|
||||
|
||||
# note: you may encounter errors like 'KeyError: 'document'"
|
||||
# when invoking events using methods from your own scripts with this
|
||||
# obvious code:
|
||||
#
|
||||
# self.loadingDocument.AddEventListener('aboutToClose',
|
||||
# self.onLoadingDialogDismissed, True)
|
||||
#
|
||||
# A workaround is to define callback methods in standalone Python
|
||||
# files with event, self, and document defined to None.
|
||||
#
|
||||
# see https://www.panda3d.org/forums/viewtopic.php?f=4&t=16412
|
||||
#
|
||||
|
||||
# Or, use this indirection technique to work around the problem,
|
||||
# by publishing the app into the context, then accessing it through
|
||||
# the document's context...
|
||||
|
||||
self.windowContext.app = self
|
||||
self.loadingDocument.AddEventListener('aboutToClose',
|
||||
'document.context.app.handleAboutToClose()', True)
|
||||
|
||||
self.loadingDocument.Show()
|
||||
|
||||
def handleAboutToClose(self):
|
||||
self.userConfirmed = True
|
||||
if self.monitorNP and self.keyboardNP:
|
||||
self.onLoadingDialogDismissed()
|
||||
|
||||
def attachCustomRocketEvent(self, document, rocketEventName, pandaHandler, once=False):
|
||||
# handle custom event
|
||||
|
||||
# note: you may encounter errors like 'KeyError: 'document'"
|
||||
# when invoking events using methods from your own scripts with this
|
||||
# obvious code:
|
||||
#
|
||||
# self.loadingDocument.AddEventListener('aboutToClose',
|
||||
# self.onLoadingDialogDismissed, True)
|
||||
#
|
||||
# see https://www.panda3d.org/forums/viewtopic.php?f=4&t=16412
|
||||
|
||||
|
||||
# this technique converts Rocket events to Panda3D events
|
||||
|
||||
pandaEvent = 'panda.' + rocketEventName
|
||||
|
||||
document.AddEventListener(
|
||||
rocketEventName,
|
||||
"messenger.send('" + pandaEvent + "', [event])")
|
||||
|
||||
if once:
|
||||
self.acceptOnce(pandaEvent, pandaHandler)
|
||||
else:
|
||||
self.accept(pandaEvent, pandaHandler)
|
||||
|
||||
|
||||
def cycleLoading(self, task):
|
||||
"""
|
||||
Update the "loading" text in the initial window until
|
||||
the user presses Space, Enter, or Escape or clicks (see loading.rxml)
|
||||
or sufficient time has elapsed (self.stopLoadingTime).
|
||||
"""
|
||||
text = self.loadingText
|
||||
|
||||
now = globalClock.getFrameTime()
|
||||
if self.monitorNP and self.keyboardNP:
|
||||
text.text = "Ready"
|
||||
if now > self.stopLoadingTime or self.userConfirmed:
|
||||
self.onLoadingDialogDismissed()
|
||||
return task.done
|
||||
elif self.loadingError:
|
||||
text.text = "Assets not found"
|
||||
else:
|
||||
count = 5
|
||||
intv = int(now * 4) % count # @UndefinedVariable
|
||||
text.text = "Loading" + ("." * (1+intv)) + (" " * (2 - intv))
|
||||
|
||||
return task.cont
|
||||
|
||||
def onLoadingDialogDismissed(self):
|
||||
""" Once a models are loaded, stop 'loading' and proceed to 'start' """
|
||||
if self.loadingDocument:
|
||||
if self.loadingTask:
|
||||
self.taskMgr.remove(self.loadingTask)
|
||||
self.loadingTask = None
|
||||
|
||||
self.showStarting()
|
||||
|
||||
def fadeOut(self, element, time):
|
||||
""" Example updating RCSS attributes from code
|
||||
by modifying the 'color' RCSS attribute to slowly
|
||||
change from solid to transparent.
|
||||
|
||||
element: the Rocket element whose style to modify
|
||||
time: time in seconds for fadeout
|
||||
"""
|
||||
|
||||
# get the current color from RCSS effective style
|
||||
color = element.style.color
|
||||
# convert to RGBA form
|
||||
prefix = color[:color.rindex(',')+1].replace('rgb(', 'rgba(')
|
||||
|
||||
def updateAlpha(t):
|
||||
# another way of setting style on a specific element
|
||||
attr = 'color: ' + prefix + str(int(t)) +');'
|
||||
element.SetAttribute('style', attr)
|
||||
|
||||
alphaInterval = LerpFunc(updateAlpha,
|
||||
duration=time,
|
||||
fromData=255,
|
||||
toData=0,
|
||||
blendType='easeIn')
|
||||
|
||||
return alphaInterval
|
||||
|
||||
def showStarting(self):
|
||||
""" Models are loaded, so update the dialog,
|
||||
fade out, then transition to the console. """
|
||||
self.loadingText.text = 'Starting...'
|
||||
|
||||
alphaInterval = self.fadeOut(self.loadingText, 0.5)
|
||||
alphaInterval.setDoneEvent('fadeOutFinished')
|
||||
|
||||
def fadeOutFinished():
|
||||
if self.loadingDocument:
|
||||
self.loadingDocument.Close()
|
||||
self.loadingDocument = None
|
||||
self.createConsole()
|
||||
|
||||
self.accept('fadeOutFinished', fadeOutFinished)
|
||||
|
||||
alphaInterval.start()
|
||||
|
||||
def createConsole(self):
|
||||
""" Create the in-world console, which displays
|
||||
a RocketRegion in a GraphicsBuffer, which appears
|
||||
in a Texture on the monitor model. """
|
||||
|
||||
self.monitorNP.reparentTo(self.render)
|
||||
self.monitorNP.setScale(1.5)
|
||||
|
||||
self.keyboardNP.reparentTo(self.render)
|
||||
self.keyboardNP.setHpr(-90, 0, 15)
|
||||
self.keyboardNP.setScale(20)
|
||||
|
||||
self.placeItems()
|
||||
|
||||
self.setupRocketConsole()
|
||||
|
||||
# re-enable mouse
|
||||
mat=Mat4(self.camera.getMat())
|
||||
mat.invertInPlace()
|
||||
self.mouseInterfaceNode.setMat(mat)
|
||||
self.enableMouse()
|
||||
|
||||
def placeItems(self):
|
||||
self.camera.setPos(0, -20, 0)
|
||||
self.camera.setHpr(0, 0, 0)
|
||||
self.monitorNP.setPos(0, 0, 1)
|
||||
self.keyboardNP.setPos(0, -5, -2.5)
|
||||
|
||||
|
||||
def setupRocketConsole(self):
|
||||
"""
|
||||
Place a new rocket window onto a texture
|
||||
bound to the front of the monitor.
|
||||
"""
|
||||
self.win.setClearColor(Vec4(0.5, 0.5, 0.8, 1))
|
||||
|
||||
faceplate = self.monitorNP.find("**/Faceplate")
|
||||
assert faceplate
|
||||
|
||||
mybuffer = self.win.makeTextureBuffer("Console Buffer", 1024, 512)
|
||||
tex = mybuffer.getTexture()
|
||||
tex.setMagfilter(Texture.FTLinear)
|
||||
tex.setMinfilter(Texture.FTLinear)
|
||||
|
||||
faceplate.setTexture(tex, 1)
|
||||
|
||||
self.rocketConsole = RocketRegion.make('console', mybuffer)
|
||||
self.rocketConsole.setInputHandler(self.inputHandler)
|
||||
|
||||
self.consoleContext = self.rocketConsole.getContext()
|
||||
self.console = console.Console(self, self.consoleContext, 40, 13, self.handleCommand)
|
||||
|
||||
self.console.addLine("Panda DOS")
|
||||
self.console.addLine("type 'help'")
|
||||
self.console.addLine("")
|
||||
|
||||
self.console.allowEditing(True)
|
||||
|
||||
def handleCommand(self, command):
|
||||
if command is None:
|
||||
# hack for Ctrl-Break
|
||||
self.spewInProgress = False
|
||||
self.console.addLine("*** break ***")
|
||||
self.console.allowEditing(True)
|
||||
return
|
||||
|
||||
command = command.strip()
|
||||
if not command:
|
||||
return
|
||||
|
||||
tokens = [x.strip() for x in command.split(' ')]
|
||||
command = tokens[0].lower()
|
||||
|
||||
if command == 'help':
|
||||
self.console.addLines([
|
||||
"Sorry, this is utter fakery.",
|
||||
"You won't get much more",
|
||||
"out of this simulation unless",
|
||||
"you program it yourself. :)"
|
||||
])
|
||||
elif command == 'dir':
|
||||
self.console.addLines([
|
||||
"Directory of C:\\:",
|
||||
"HELP COM 72 05-06-2015 14:07",
|
||||
"DIR COM 121 05-06-2015 14:11",
|
||||
"SPEW COM 666 05-06-2015 15:02",
|
||||
" 2 Files(s) 859 Bytes.",
|
||||
" 0 Dirs(s) 7333 Bytes free.",
|
||||
""])
|
||||
elif command == 'cls':
|
||||
self.console.cls()
|
||||
elif command == 'echo':
|
||||
self.console.addLine(' '.join(tokens[1:]))
|
||||
elif command == 'ver':
|
||||
self.console.addLine('Panda DOS v0.01 in Panda3D ' + PandaSystem.getVersionString())
|
||||
elif command == 'spew':
|
||||
self.startSpew()
|
||||
elif command == 'exit':
|
||||
self.console.setPrompt("System is shutting down NOW!")
|
||||
self.terminateMonitor()
|
||||
else:
|
||||
self.console.addLine("command not found")
|
||||
|
||||
def startSpew(self):
|
||||
self.console.allowEditing(False)
|
||||
self.console.addLine("LINE NOISE 1.0")
|
||||
self.console.addLine("")
|
||||
|
||||
self.spewInProgress = True
|
||||
|
||||
# note: spewage always occurs in 'doMethodLater';
|
||||
# time.sleep() would be pointless since the whole
|
||||
# UI would be frozen during the wait.
|
||||
self.queueSpew(2)
|
||||
|
||||
def queueSpew(self, delay=0.1):
|
||||
self.taskMgr.doMethodLater(delay, self.spew, 'spew')
|
||||
|
||||
def spew(self, task):
|
||||
# generate random spewage, just like on TV!
|
||||
if not self.spewInProgress:
|
||||
return
|
||||
|
||||
def randchr():
|
||||
return chr(int(random.random() < 0.25 and 32 or random.randint(32, 127)))
|
||||
|
||||
line = ''.join([randchr() for _ in range(40) ])
|
||||
|
||||
self.console.addLine(line)
|
||||
self.queueSpew()
|
||||
|
||||
def terminateMonitor(self):
|
||||
alphaInterval = self.fadeOut(self.console.getTextContainer(), 2)
|
||||
|
||||
alphaInterval.setDoneEvent('fadeOutFinished')
|
||||
|
||||
def fadeOutFinished():
|
||||
sys.exit(0)
|
||||
|
||||
self.accept('fadeOutFinished', fadeOutFinished)
|
||||
|
||||
alphaInterval.start()
|
||||
|
||||
app = MyApp()
|
||||
app.run()
|
Loading…
x
Reference in New Issue
Block a user