aboutsummaryrefslogtreecommitdiff
path: root/lib/lua/src/lfunc.c
blob: 813e88f5831bb9cfb6f5dabfae930df30231fa67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/


#include <stddef.h>

#define lfunc_c
#define LUA_CORE

#include "lua.h"

#include "lfunc.h"
#include "lgc.h"
#include "lmem.h"
#include "lobject.h"
#include "lstate.h"



Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {
  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
  luaC_link(L, obj2gco(c), LUA_TFUNCTION);
  c->c.isC = 1;
  c->c.env = e;
  c->c.nupvalues = cast_byte(nelems);
  return c;
}


Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {
  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
  luaC_link(L, obj2gco(c), LUA_TFUNCTION);
  c->l.isC = 0;
  c->l.env = e;
  c->l.nupvalues = cast_byte(nelems);
  while (nelems--) c->l.upvals[nelems] = NULL;
  return c;
}


UpVal *luaF_newupval (lua_State *L) {
  UpVal *uv = luaM_new(L, UpVal);
  luaC_link(L, obj2gco(uv), LUA_TUPVAL);
  uv->v = &uv->u.value;
  setnilvalue(uv->v);
  return uv;
}


UpVal *luaF_findupval (lua_State *L, StkId level) {
  global_State *g = G(L);
  GCObject **pp = &L->openupval;
  UpVal *p;
  UpVal *uv;
  while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {
    lua_assert(p->v != &p->u.value);
    if (p->v == level) {  /* found a corresponding upvalue? */
      if (isdead(g, obj2gco(p)))  /* is it dead? */
        changewhite(obj2gco(p));  /* ressurect it */
      return p;
    }
    pp = &p->next;
  }
  uv = luaM_new(L, UpVal);  /* not found: create a new one */
  uv->tt = LUA_TUPVAL;
  uv->marked = luaC_white(g);
  uv->v = level;  /* current value lives in the stack */
  uv->next = *pp;  /* chain it in the proper position */
  *pp = obj2gco(uv);
  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */
  uv->u.l.next = g->uvhead.u.l.next;
  uv->u.l.next->u.l.prev = uv;
  g->uvhead.u.l.next = uv;
  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
  return uv;
}


static void unlinkupval (UpVal *uv) {
  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */
  uv->u.l.prev->u.l.next = uv->u.l.next;
}


void luaF_freeupval (lua_State *L, UpVal *uv) {
  if (uv->v != &uv->u.value)  /* is it open? */
    unlinkupval(uv);  /* remove from open list */
  luaM_free(L, uv);  /* free upvalue */
}


void luaF_close (lua_State *L, StkId level) {
  UpVal *uv;
  global_State *g = G(L);
  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {
    GCObject *o = obj2gco(uv);
    lua_assert(!isblack(o) && uv->v != &uv->u.value);
    L->openupval = uv->next;  /* remove from `open' list */
    if (isdead(g, o))
      luaF_freeupval(L, uv);  /* free upvalue */
    else {
      unlinkupval(uv);
      setobj(L, &uv->u.value, uv->v);
      uv->v = &uv->u.value;  /* now current value lives here */
      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */
    }
  }
}


Proto *luaF_newproto (lua_State *L) {
  Proto *f = luaM_new(L, Proto);
  luaC_link(L, obj2gco(f), LUA_TPROTO);
  f->k = NULL;
  f->sizek = 0;
  f->p = NULL;
  f->sizep = 0;
  f->code = NULL;
  f->sizecode = 0;
  f->sizelineinfo = 0;
  f->sizeupvalues = 0;
  f->nups = 0;
  f->upvalues = NULL;
  f->numparams = 0;
  f->is_vararg = 0;
  f->maxstacksize = 0;
  f->lineinfo = NULL;
  f->sizelocvars = 0;
  f->locvars = NULL;
  f->linedefined = 0;
  f->lastlinedefined = 0;
  f->source = NULL;
  return f;
}


void luaF_freeproto (lua_State *L, Proto *f) {
  luaM_freearray(L, f->code, f->sizecode, Instruction);
  luaM_freearray(L, f->p, f->sizep, Proto *);
  luaM_freearray(L, f->k, f->sizek, TValue);
  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
  luaM_free(L, f);
}


void luaF_freeclosure (lua_State *L, Closure *c) {
  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
                          sizeLclosure(c->l.nupvalues);
  luaM_freemem(L, c, size);
}


/*
** Look for n-th local variable at line `line' in function `func'.
** Returns NULL if not found.
*/
const char *luaF_getlocalname (const Proto *f, int local_number, int pc) {
  int i;
  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {
    if (pc < f->locvars[i].endpc) {  /* is variable active? */
      local_number--;
      if (local_number == 0)
        return getstr(f->locvars[i].varname);
    }
  }
  return NULL;  /* not found */
}

"hl com">/******************************************************************************/ /** MenuMusicFetcher */ /******************************************************************************/ void MenuMusicFetcher::fetchSounds(const std::string &name, std::set<std::string> &dst_paths, std::set<std::string> &dst_datas) { if(m_fetched.count(name)) return; m_fetched.insert(name); std::string base; base = porting::path_share + DIR_DELIM + "sounds"; dst_paths.insert(base + DIR_DELIM + name + ".ogg"); int i; for(i=0; i<10; i++) dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg"); base = porting::path_user + DIR_DELIM + "sounds"; dst_paths.insert(base + DIR_DELIM + name + ".ogg"); for(i=0; i<10; i++) dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg"); } /******************************************************************************/ /** GUIEngine */ /******************************************************************************/ GUIEngine::GUIEngine(JoystickController *joystick, gui::IGUIElement *parent, IMenuManager *menumgr, MainMenuData *data, bool &kill) : m_parent(parent), m_menumanager(menumgr), m_smgr(RenderingEngine::get_scene_manager()), m_data(data), m_kill(kill) { //initialize texture pointers for (image_definition &texture : m_textures) { texture.texture = NULL; } // is deleted by guiformspec! m_buttonhandler = new TextDestGuiEngine(this); //create texture source m_texture_source = new MenuTextureSource(RenderingEngine::get_video_driver()); //create soundmanager MenuMusicFetcher soundfetcher; #if USE_SOUND if (g_settings->getBool("enable_sound")) m_sound_manager = createOpenALSoundManager(g_sound_manager_singleton.get(), &soundfetcher); #endif if(!m_sound_manager) m_sound_manager = &dummySoundManager; //create topleft header m_toplefttext = L""; core::rect<s32> rect(0, 0, g_fontengine->getTextWidth(m_toplefttext.c_str()), g_fontengine->getTextHeight()); rect += v2s32(4, 0); m_irr_toplefttext = gui::StaticText::add(RenderingEngine::get_gui_env(), m_toplefttext, rect, false, true, 0, -1); //create formspecsource m_formspecgui = new FormspecFormSource(""); /* Create menu */ m_menu = new GUIFormSpecMenu(joystick, m_parent, -1, m_menumanager, NULL /* &client */, m_texture_source, m_formspecgui, m_buttonhandler, "", false); m_menu->allowClose(false); m_menu->lockSize(true,v2u32(800,600)); // Initialize scripting infostream << "GUIEngine: Initializing Lua" << std::endl; m_script = new MainMenuScripting(this); try { m_script->setMainMenuData(&m_data->script_data); m_data->script_data.errormessage = ""; if (!loadMainMenuScript()) { errorstream << "No future without main menu!" << std::endl; abort(); } run(); } catch (LuaError &e) { errorstream << "Main menu error: " << e.what() << std::endl; m_data->script_data.errormessage = e.what(); } m_menu->quitMenu(); m_menu->drop(); m_menu = NULL; } /******************************************************************************/ bool GUIEngine::loadMainMenuScript() { // Set main menu path (for core.get_mainmenu_path()) m_scriptdir = g_settings->get("main_menu_path"); if (m_scriptdir.empty()) { m_scriptdir = porting::path_share + DIR_DELIM + "builtin" + DIR_DELIM + "mainmenu"; } // Load builtin (which will load the main menu script) std::string script = porting::path_share + DIR_DELIM "builtin" + DIR_DELIM "init.lua"; try { m_script->loadScript(script); // Menu script loaded return true; } catch (const ModError &e) { errorstream << "GUIEngine: execution of menu script failed: " << e.what() << std::endl; } return false; } /******************************************************************************/ void GUIEngine::run() { // Always create clouds because they may or may not be // needed based on the game selected video::IVideoDriver *driver = RenderingEngine::get_video_driver(); cloudInit(); unsigned int text_height = g_fontengine->getTextHeight(); irr::core::dimension2d<u32> previous_screen_size(g_settings->getU16("screen_w"), g_settings->getU16("screen_h")); static const video::SColor sky_color(255, 140, 186, 250); // Reset fog color { video::SColor fog_color; video::E_FOG_TYPE fog_type = video::EFT_FOG_LINEAR; f32 fog_start = 0; f32 fog_end = 0; f32 fog_density = 0; bool fog_pixelfog = false; bool fog_rangefog = false; driver->getFog(fog_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); driver->setFog(sky_color, fog_type, fog_start, fog_end, fog_density, fog_pixelfog, fog_rangefog); } while (RenderingEngine::run() && (!m_startgame) && (!m_kill)) { const irr::core::dimension2d<u32> &current_screen_size = RenderingEngine::get_video_driver()->getScreenSize(); // Verify if window size has changed and save it if it's the case // Ensure evaluating settings->getBool after verifying screensize // First condition is cheaper if (previous_screen_size != current_screen_size && current_screen_size != irr::core::dimension2d<u32>(0,0) && g_settings->getBool("autosave_screensize")) { g_settings->setU16("screen_w", current_screen_size.Width); g_settings->setU16("screen_h", current_screen_size.Height); previous_screen_size = current_screen_size; } //check if we need to update the "upper left corner"-text if (text_height != g_fontengine->getTextHeight()) { updateTopLeftTextSize(); text_height = g_fontengine->getTextHeight(); } driver->beginScene(true, true, sky_color); if (m_clouds_enabled) { cloudPreProcess(); drawOverlay(driver); } else drawBackground(driver); drawHeader(driver); drawFooter(driver); RenderingEngine::get_gui_env()->drawAll(); driver->endScene(); if (m_clouds_enabled) cloudPostProcess(); else sleep_ms(25); m_script->step(); #ifdef __ANDROID__ m_menu->getAndroidUIInput(); #endif } } /******************************************************************************/ GUIEngine::~GUIEngine() { if (m_sound_manager != &dummySoundManager){ delete m_sound_manager; m_sound_manager = NULL; } infostream<<"GUIEngine: Deinitializing scripting"<<std::endl; delete m_script; m_irr_toplefttext->setText(L""); //clean up texture pointers for (image_definition &texture : m_textures) { if (texture.texture) RenderingEngine::get_video_driver()->removeTexture(texture.texture); } delete m_texture_source; if (m_cloud.clouds) m_cloud.clouds->drop(); } /******************************************************************************/ void GUIEngine::cloudInit() { m_cloud.clouds = new Clouds(m_smgr, -1, rand()); m_cloud.clouds->setHeight(100.0f); m_cloud.clouds->update(v3f(0, 0, 0), video::SColor(255,240,240,255)); m_cloud.camera = m_smgr->addCameraSceneNode(0, v3f(0,0,0), v3f(0, 60, 100)); m_cloud.camera->setFarValue(10000); m_cloud.lasttime = RenderingEngine::get_timer_time(); } /******************************************************************************/ void GUIEngine::cloudPreProcess() { u32 time = RenderingEngine::get_timer_time(); if(time > m_cloud.lasttime) m_cloud.dtime = (time - m_cloud.lasttime) / 1000.0; else m_cloud.dtime = 0; m_cloud.lasttime = time; m_cloud.clouds->step(m_cloud.dtime*3); m_cloud.clouds->render(); m_smgr->drawAll(); }