<commit_before>#include <Windows.h>
#include <base/hook/iat.h>
#include <base/hook/eat.h>
#include <base/hook/fp_call.h>
#include <base/win/process.h>
#include "utility.h"

#pragma data_seg("Shared")
bool                         shared_enable = false;
uint16_t                     shared_port   = 0;
wchar_t                      shared_luadll_str[MAX_PATH] = {0};
size_t                       shared_luadll_len = 0;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")

std::wstring_view shared_luadll(shared_luadll_str, shared_luadll_len);

void initialize_debugger(void* L)
{
	if (GetModuleHandleW(L"debugger.dll")) {
		return;
	}
	fs::path debugger = get_self_path().remove_filename() / L"debugger.dll";
	HMODULE dll = LoadLibraryW(debugger.c_str());
	if (!dll) {
		return;
	}
	uintptr_t set_luadll   = (uintptr_t)GetProcAddress(dll, "set_luadll");
	uintptr_t start_server = (uintptr_t)GetProcAddress(dll, "start_server");
	uintptr_t attach_lua   = (uintptr_t)GetProcAddress(dll, "attach_lua");
	if (!set_luadll || !start_server || !attach_lua) {
		return;
	}
	if (shared_luadll.size() != 0) {
		base::c_call<void>(set_luadll, shared_luadll.data(), shared_luadll.size());
	}
	shared_port = base::c_call<uint16_t>(start_server, "127.0.0.1", 0, true);
	base::c_call<void>(attach_lua, L, true);
}

void uninitialize_debugger(void* L)
{
	HMODULE dll = GetModuleHandleW(L"debugger.dll");
	if (!dll) {
		return;
	}
	uintptr_t detach_lua = (uintptr_t)GetProcAddress(dll, "detach_lua");
	if (!detach_lua) {
		return;
	}
	base::c_call<void>(detach_lua, L);
	Sleep(1000);
}

struct lua_newstate
	: public hook_helper<lua_newstate>
{
	static void* __cdecl fake(void* f, void* ud)
	{
		void* L = base::c_call<void*>(real, f, ud);
		if (L) initialize_debugger(L);
		return L;
	}
};

struct luaL_newstate
	: public hook_helper<lua_newstate>
{
	static void* __cdecl fake()
	{
		void* L = base::c_call<void*>(real);

		if (L) initialize_debugger(L);
		return L;
	}
};

struct lua_close
	: public hook_helper<lua_close>
{
	static void __cdecl fake(void* L)
	{
		uninitialize_debugger(L);
		return base::c_call<void>(real, L);
	}
};

BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID /*pReserved*/)
{
	if (reason == DLL_PROCESS_ATTACH)
	{
		::DisableThreadLibraryCalls(module);
		if (shared_enable) {
			if (shared_luadll.size() != 0) {
				lua_newstate::init(shared_luadll.data(), "lua_newstate");
				luaL_newstate::init(shared_luadll.data(), "luaL_newstate");
				lua_close::init(shared_luadll.data(), "lua_close");
			}
			else {
				const char* luadll = search_api("lua_newstate", "luaL_newstate");
				if (luadll) {
					lua_newstate::init(luadll, "lua_newstate");
					luaL_newstate::init(luadll, "luaL_newstate");
					lua_close::init(luadll, "lua_close");
				}
				else {
					lua_newstate::init(L"luacore.dll", "lua_newstate");
					luaL_newstate::init(L"luacore.dll", "luaL_newstate");
					lua_close::init(L"luacore.dll", "lua_close");
				}
			}
		}
	}
	return TRUE;
}

extern "C" __declspec(dllexport)
bool set_luadll(const wchar_t* str, size_t len)
{
	if (len + 1 > _countof(shared_luadll_str)) { return false; }
	memcpy(shared_luadll_str, str, len * sizeof(wchar_t));
	shared_luadll_str[len] = L'\0';
	shared_luadll_len = len;
	return true;
}

extern "C" __declspec(dllexport)
uint16_t create_process_with_debugger(const wchar_t* application, const wchar_t* command_line, const wchar_t* current_directory)
{
	shared_port = 0;
	shared_enable = true;

	base::win::process p;
	p.inject(get_self_path());
	if (!p.create(application, command_line, current_directory)) {
		return 0;
	}
	for (int i = 0; i < 1000 || !p.is_running(); ++i)
	{
		if (shared_port != 0)
			return shared_port;
		Sleep(100);
	}
	return 0;
}
<commit_msg>修正一个错误<commit_after>#include <Windows.h>
#include <base/hook/iat.h>
#include <base/hook/eat.h>
#include <base/hook/fp_call.h>
#include <base/win/process.h>
#include "utility.h"

#pragma data_seg("Shared")
bool                         shared_enable = false;
uint16_t                     shared_port   = 0;
wchar_t                      shared_luadll_str[MAX_PATH] = {0};
size_t                       shared_luadll_len = 0;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")

std::wstring_view shared_luadll(shared_luadll_str, shared_luadll_len);

void initialize_debugger(void* L)
{
	if (GetModuleHandleW(L"debugger.dll")) {
		return;
	}
	fs::path debugger = get_self_path().remove_filename() / L"debugger.dll";
	HMODULE dll = LoadLibraryW(debugger.c_str());
	if (!dll) {
		return;
	}
	uintptr_t set_luadll   = (uintptr_t)GetProcAddress(dll, "set_luadll");
	uintptr_t start_server = (uintptr_t)GetProcAddress(dll, "start_server");
	uintptr_t attach_lua   = (uintptr_t)GetProcAddress(dll, "attach_lua");
	if (!set_luadll || !start_server || !attach_lua) {
		return;
	}
	if (shared_luadll.size() != 0) {
		base::c_call<void>(set_luadll, shared_luadll.data(), shared_luadll.size());
	}
	shared_port = base::c_call<uint16_t>(start_server, "127.0.0.1", 0, true);
	base::c_call<void>(attach_lua, L, true);
}

void uninitialize_debugger(void* L)
{
	HMODULE dll = GetModuleHandleW(L"debugger.dll");
	if (!dll) {
		return;
	}
	uintptr_t detach_lua = (uintptr_t)GetProcAddress(dll, "detach_lua");
	if (!detach_lua) {
		return;
	}
	base::c_call<void>(detach_lua, L);
	Sleep(1000);
}

struct lua_newstate
	: public hook_helper<lua_newstate>
{
	static void* __cdecl fake(void* f, void* ud)
	{
		void* L = base::c_call<void*>(real, f, ud);
		if (L) initialize_debugger(L);
		return L;
	}
};

struct luaL_newstate
	: public hook_helper<luaL_newstate>
{
	static void* __cdecl fake()
	{
		void* L = base::c_call<void*>(real);

		if (L) initialize_debugger(L);
		return L;
	}
};

struct lua_close
	: public hook_helper<lua_close>
{
	static void __cdecl fake(void* L)
	{
		uninitialize_debugger(L);
		return base::c_call<void>(real, L);
	}
};

BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID /*pReserved*/)
{
	if (reason == DLL_PROCESS_ATTACH)
	{
		::DisableThreadLibraryCalls(module);
		if (shared_enable) {
			if (shared_luadll.size() != 0) {
				lua_newstate::init(shared_luadll.data(), "lua_newstate");
				luaL_newstate::init(shared_luadll.data(), "luaL_newstate");
				lua_close::init(shared_luadll.data(), "lua_close");
			}
			else {
				const char* luadll = search_api("lua_newstate", "luaL_newstate");
				if (luadll) {
					lua_newstate::init(luadll, "lua_newstate");
					luaL_newstate::init(luadll, "luaL_newstate");
					lua_close::init(luadll, "lua_close");
				}
				else {
					lua_newstate::init(L"luacore.dll", "lua_newstate");
					luaL_newstate::init(L"luacore.dll", "luaL_newstate");
					lua_close::init(L"luacore.dll", "lua_close");
				}
			}
		}
	}
	return TRUE;
}

extern "C" __declspec(dllexport)
bool set_luadll(const wchar_t* str, size_t len)
{
	if (len + 1 > _countof(shared_luadll_str)) { return false; }
	memcpy(shared_luadll_str, str, len * sizeof(wchar_t));
	shared_luadll_str[len] = L'\0';
	shared_luadll_len = len;
	return true;
}

extern "C" __declspec(dllexport)
uint16_t create_process_with_debugger(const wchar_t* application, const wchar_t* command_line, const wchar_t* current_directory)
{
	shared_port = 0;
	shared_enable = true;

	base::win::process p;
	p.inject(get_self_path());
	if (!p.create(application, command_line, current_directory)) {
		return 0;
	}
	for (int i = 0; i < 1000 || !p.is_running(); ++i)
	{
		if (shared_port != 0)
			return shared_port;
		Sleep(100);
	}
	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCLCPP__TIME_HPP_
#define RCLCPP__TIME_HPP_

#include <utility>

#include "builtin_interfaces/msg/time.hpp"

#include "rclcpp/exceptions.hpp"

namespace rclcpp
{

class Time
{
public:
  template<rcl_time_source_type_t ClockT = RCL_SYSTEM_TIME>
  static Time
  now()
  {
    rcutils_time_point_value_t rcutils_now = 0;
    rcutils_ret_t ret = RCUTILS_RET_ERROR;
    if (ClockT == RCL_ROS_TIME) {
      throw std::runtime_error("RCL_ROS_TIME is currently not implemented.");
      ret = false;
    } else if (ClockT == RCL_SYSTEM_TIME) {
      ret = rcutils_system_time_now(&rcutils_now);
    } else if (ClockT == RCL_STEADY_TIME) {
      ret = rcutils_steady_time_now(&rcutils_now);
    }
    if (ret != RCUTILS_RET_OK) {
      rclcpp::exceptions::throw_from_rcl_error(
        ret, "Could not get current time: ");
    }

    return Time(std::move(rcutils_now));
  }

  operator builtin_interfaces::msg::Time() const
  {
    builtin_interfaces::msg::Time msg_time;
    msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_));
    msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_ % (1000 * 1000 * 1000));
    return msg_time;
  }

private:
  rcl_time_point_value_t rcl_time_;

  Time(std::uint32_t sec, std::uint32_t nanosec)
  : rcl_time_(RCL_S_TO_NS(sec) + nanosec)
  {}

  explicit Time(rcl_time_point_value_t && rcl_time)
  : rcl_time_(std::forward<decltype(rcl_time)>(rcl_time))
  {}
};

}  // namespace rclcpp

#endif  // RCLCPP__TIME_HPP_
<commit_msg>include rcutils/time (#333)<commit_after>// Copyright 2017 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCLCPP__TIME_HPP_
#define RCLCPP__TIME_HPP_

#include <utility>

#include "builtin_interfaces/msg/time.hpp"
#include "rcl/time.h"
#include "rcutils/time.h"

#include "rclcpp/exceptions.hpp"

namespace rclcpp
{

class Time
{
public:
  template<rcl_time_source_type_t ClockT = RCL_SYSTEM_TIME>
  static Time
  now()
  {
    rcutils_time_point_value_t rcutils_now = 0;
    rcutils_ret_t ret = RCUTILS_RET_ERROR;
    if (ClockT == RCL_ROS_TIME) {
      throw std::runtime_error("RCL_ROS_TIME is currently not implemented.");
      ret = false;
    } else if (ClockT == RCL_SYSTEM_TIME) {
      ret = rcutils_system_time_now(&rcutils_now);
    } else if (ClockT == RCL_STEADY_TIME) {
      ret = rcutils_steady_time_now(&rcutils_now);
    }
    if (ret != RCUTILS_RET_OK) {
      rclcpp::exceptions::throw_from_rcl_error(
        ret, "Could not get current time: ");
    }

    return Time(std::move(rcutils_now));
  }

  operator builtin_interfaces::msg::Time() const
  {
    builtin_interfaces::msg::Time msg_time;
    msg_time.sec = static_cast<std::int32_t>(RCL_NS_TO_S(rcl_time_));
    msg_time.nanosec = static_cast<std::uint32_t>(rcl_time_ % (1000 * 1000 * 1000));
    return msg_time;
  }

private:
  rcl_time_point_value_t rcl_time_;

  Time(std::uint32_t sec, std::uint32_t nanosec)
  : rcl_time_(RCL_S_TO_NS(sec) + nanosec)
  {}

  explicit Time(rcl_time_point_value_t && rcl_time)
  : rcl_time_(std::forward<decltype(rcl_time)>(rcl_time))
  {}
};

}  // namespace rclcpp

#endif  // RCLCPP__TIME_HPP_
<|endoftext|>


<commit_before>#include "cssysdef.h"

#include <ctype.h>

#include "awstimer.h"
#include "awstxtbx.h"
#include "ivideo/graph2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "csutil/scfstr.h"
#include "iutil/evdefs.h"

#include <stdio.h>

const int awsTextBox::fsNormal = 0x0;
const int awsTextBox::fsBitmap = 0x1;

const int awsTextBox::signalChanged = 0x1;
const int awsTextBox::signalLostFocus = 0x2;
const int awsTextBox::signalEnterPressed = 0x3;
const int awsTextBox::signalTabPressed = 0x4;
const int awsTextBox::signalFocused = 0x5;

static iAwsSink *textbox_sink = 0;

CS_IMPLEMENT_STATIC_VAR (GetTextBoxBlinkingCursorSlot, awsSlot,())

static awsSlot *textbox_slot = NULL;

static void BlinkCursor (void *, iAwsSource *source)
{
  iAwsComponent *comp = source->GetComponent ();

  //  Setting blink actually forces an inversion of blink's property, and if the textbox is the

  // focus then it will be Invalidated as well.
  comp->SetProperty ("Blink", 0);
}

awsTextBox::awsTextBox () :
  mouse_is_over(false),
  has_focus(false),
  should_mask(0),
  bkg(NULL),
  frame_style(0),
  alpha_level(92),
  text(NULL),
  disallow(NULL),
  maskchar(NULL),
  start(0),
  cursor(0),
  blink_timer(NULL),
  blink(true)
{
  textbox_slot = GetTextBoxBlinkingCursorSlot ();
}

awsTextBox::~awsTextBox ()
{
  if (blink_timer != 0)
  {
    textbox_slot->Disconnect (
        blink_timer,
        awsTimer::signalTick,
        textbox_sink,
        textbox_sink->GetTriggerID ("Blink"));
    delete blink_timer;
  }
}

const char *awsTextBox::Type ()
{
  return "Text Box";
}

bool awsTextBox::Setup (iAws *_wmgr, iAwsComponentNode *settings)
{
  if (!awsComponent::Setup (_wmgr, settings)) return false;

  // Setup blink event handling
  if (textbox_sink == 0)
  {
    textbox_sink = WindowManager ()->GetSinkMgr ()->CreateSink (NULL);
    textbox_sink->RegisterTrigger ("Blink", &BlinkCursor);
  }

  blink_timer = new awsTimer (WindowManager ()->GetObjectRegistry (), this);
  blink_timer->SetTimer (350);
  blink_timer->Start ();

  textbox_slot->Connect (
      blink_timer,
      awsTimer::signalTick,
      textbox_sink,
      textbox_sink->GetTriggerID ("Blink"));

  ////////////////
  iAwsPrefManager *pm = WindowManager ()->GetPrefMgr ();

  pm->LookupIntKey ("ButtonTextureAlpha", alpha_level); // global get
  pm->GetInt (settings, "Style", frame_style);
  pm->GetInt (settings, "Alpha", alpha_level);          // local overrides, if present.
  pm->GetInt (settings, "Masked", should_mask);
  pm->GetString (settings, "Text", text);
  pm->GetString (settings, "Disallow", disallow);
  pm->GetString (settings, "MaskChar", maskchar);

  if (text) {
      cursor = text->Length ();
      text = new scfString(*text);
  } else
    text = new scfString ();

  switch (frame_style)
  {
    case fsNormal:
      bkg = pm->GetTexture ("Texture");
      break;

    case fsBitmap:
      {
        iString *tn1 = NULL;

        pm->GetString (settings, "Bitmap", tn1);

        if (tn1) bkg = pm->GetTexture (tn1->GetData (), tn1->GetData ());
      }
      break;
  }

  return true;
}

bool awsTextBox::GetProperty (const char *name, void **parm)
{
  if (awsComponent::GetProperty (name, parm)) return true;

  if (strcmp ("Text", name) == 0)
  {
    char *st = NULL;

    if (text) st = text->GetData ();

    iString *s = new scfString (st);
    *parm = (void *)s;
    return true;
  }
  else if (strcmp ("Disallow", name) == 0)
  {
    char *st = NULL;

    if (disallow) st = disallow->GetData ();

    iString *s = new scfString (st);
    *parm = (void *)s;
    return true;
  }

  return false;
}

bool awsTextBox::SetProperty (const char *name, void *parm)
{
  if (awsComponent::SetProperty (name, parm)) return true;

  if (strcmp ("Blink", name) == 0)
  {
    blink = !blink;
    if (has_focus) Invalidate ();
    return true;
  }
  else if (strcmp ("Text", name) == 0)
  {
    iString *s = (iString *) (parm);

    if (s)
    {
      if (text) text->DecRef ();
      text = s;
      text->IncRef ();
      Invalidate ();
      start = 0;
      cursor = 0;
    }

    return true;
  }
  else if (strcmp ("Disallow", name) == 0)
  {
    iString *s = (iString *) (parm);

    if (s)
    {
      if (disallow) disallow->DecRef ();
      disallow = s;
      disallow->IncRef ();
    }

    return true;
  }

  return false;
}

void awsTextBox::OnDraw (csRect /*clip*/)
{
  iGraphics2D *g2d = WindowManager ()->G2D ();
  iGraphics3D *g3d = WindowManager ()->G3D ();

  int hi = WindowManager ()->GetPrefMgr ()->GetColor (AC_HIGHLIGHT);
  int hi2 = WindowManager ()->GetPrefMgr ()->GetColor (AC_HIGHLIGHT2);
  int lo = WindowManager ()->GetPrefMgr ()->GetColor (AC_SHADOW);
  int lo2 = WindowManager ()->GetPrefMgr ()->GetColor (AC_SHADOW2);
  int dfill = WindowManager ()->GetPrefMgr ()->GetColor (AC_DARKFILL);
  int black = WindowManager ()->GetPrefMgr ()->GetColor (AC_BLACK);

  switch (frame_style)
  {
    case fsNormal:
      g2d->DrawLine (
          Frame ().xmin + 0,
          Frame ().ymin + 0,
          Frame ().xmax - 1,
          Frame ().ymin + 0,
          lo2);
      g2d->DrawLine (
          Frame ().xmin + 0,
          Frame ().ymin + 0,
          Frame ().xmin + 0,
          Frame ().ymax - 1,
          lo2);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymin + 1,
          Frame ().xmax - 0,
          Frame ().ymin + 1,
          lo);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymin + 1,
          Frame ().xmin + 1,
          Frame ().ymax - 0,
          lo);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymax - 0,
          Frame ().xmax - 0,
          Frame ().ymax - 0,
          hi);
      g2d->DrawLine (
          Frame ().xmax - 0,
          Frame ().ymin + 1,
          Frame ().xmax - 0,
          Frame ().ymax - 0,
          hi);

      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymin + 2,
          Frame ().xmax - 1,
          Frame ().ymin + 2,
          black);
      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymin + 2,
          Frame ().xmin + 2,
          Frame ().ymax - 1,
          black);
      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymax - 1,
          Frame ().xmax - 1,
          Frame ().ymax - 1,
          hi2);
      g2d->DrawLine (
          Frame ().xmax - 1,
          Frame ().ymin + 2,
          Frame ().xmax - 1,
          Frame ().ymax - 1,
          hi2);

      g2d->DrawBox (
          Frame ().xmin + 3,
          Frame ().ymin + 3,
          Frame ().Width () - 3,
          Frame ().Height () - 3,
          dfill);

      if (bkg)
      {
        g3d->DrawPixmap (
            bkg,
            Frame ().xmin,
            Frame ().ymin,
            Frame ().Width () + 1,
            Frame ().Height () + 1,
            0,
            0,
            Frame ().Width () + 1,
            Frame ().Height () + 1,
            alpha_level);
      }
      break;

    case fsBitmap:
      if (bkg)
      {
        g3d->DrawPixmap (
            bkg,
            Frame ().xmin,
            Frame ().ymin,
            Frame ().Width (),
            Frame ().Height (),
            0,
            0,
            Frame ().Width (),
            Frame ().Height (),
            alpha_level);
      }
      break;
  }

  // Draw the caption, if there is one and the style permits it.
  if (text && text->Length ())
  {
    int tw, th, tx, ty, mcc;
    iString *saved = NULL;

    if (should_mask && maskchar)
    {
      saved = text->Clone ();

      unsigned int i;
      for (i = 0; i < text->Length (); ++i)
        text->SetAt (i, maskchar->GetAt (0));
    }

    // Get the maximum number of characters we can use
    mcc = WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->GetLength (
        text->GetData () + start,
        Frame ().Width () - 10);

    if (mcc)
    {

      // Check to see if we're getting weird.
      // this was changed to avoid
      // jittering in the start value
      if ((int)cursor > start + mcc) start = cursor - mcc;
      if (start < 0) start = 0;

      // Make the text the right length
      scfString tmp (text->GetData () + start);
      tmp.Truncate (mcc);

      // Get the size of the text
      WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
          GetDimensions (tmp.GetData (), tw, th);

      // Calculate the center
      tx = 4;
      ty = (Frame ().Height () >> 1) - (th >> 1);

      // Draw the text
      g2d->Write (
      WindowManager ()->GetPrefMgr ()->GetDefaultFont (),
      Frame ().xmin + tx,
      Frame ().ymin + ty,
      WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE),
      -1,
      tmp.GetData ());

      if (should_mask && maskchar && saved)
      {
    text->Clear ();
    text->Append (saved);
    saved->Clear ();
    saved->DecRef ();
      }

    if (has_focus && blink)
    {
      int co, cx, tty;
      co = cursor - start;
      tmp.Truncate (co);
      // figure out where to put the cursor
      WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
         GetDimensions (tmp, cx, tty);
      g2d->DrawLine (
          Frame ().xmin + tx + cx + 1,
          Frame ().ymin + ty,
          Frame ().xmin + tx + cx + 1,
          Frame ().ymin + ty + th,
          WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE));
    }
    }
  }
  else if (has_focus && blink)
  {
    g2d->DrawLine (
        Frame ().xmin + 5,
        Frame ().ymin + 5,
        Frame ().xmin + 5,
        Frame ().ymax - 5,
        WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE));
  }
}

bool awsTextBox::OnMouseDown (int, int x, int y)
{
  // make sure text is valid
  if (text && text->Length() > 0)
  {
    // determine how many chars in the mouse was clicked
    int tp,cp;
    scfString tmp(text->GetData () + start);
    tp = x - 4 - Frame ().xmin;
    cp = WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
      GetLength(tmp,tp);
    cursor = cp + start;
  }
  // This is needed to get keyboard focus for the mouse!
  return true;
}

bool awsTextBox::OnMouseExit ()
{
  mouse_is_over = false;
  Invalidate ();
  return true;
}

bool awsTextBox::OnMouseEnter ()
{
  mouse_is_over = true;
  Invalidate ();
  return true;
}

bool awsTextBox::OnKeypress (int key, int Char, int)
{
  switch (key)
  {
    case CSKEY_ENTER:
      Broadcast (signalEnterPressed);
      break;

    case CSKEY_TAB:
      Broadcast (signalTabPressed);
      break;

    case CSKEY_BACKSPACE:
      if (cursor > 0)
      {
        cursor--;
        if (cursor - start < 5) start = cursor - 5;
        if (start < 0) start = 0;
        if (text && (text->Length () > 1))
          if (cursor == text->Length ())
            text->Truncate (text->Length () - 1);
          else
          {
            scfString tmp(text->GetData());
            tmp.Truncate (cursor);
            tmp.Append (text->GetData()+cursor+1);
            text->Replace(&tmp);
          }
        else
          text->Clear ();
      }

      break;

    case CSKEY_DEL:
      if (cursor > 0 && cursor == text->Length ()) cursor--;
      if (cursor - start < 5) start = cursor - 5;
      if (start < 0) start = 0;
      if (text && (text->Length () > 1))
        if (cursor == text->Length ())
          text->Truncate (text->Length () - 1);
        else
        {
          scfString tmp(text->GetData());
          tmp.Truncate (cursor);
          tmp.Append (text->GetData()+cursor+1);
          text->Replace(&tmp);
        }
      else
        text->Clear ();

      break;

    case CSKEY_LEFT:
      if (cursor > 0) cursor--;
      if (cursor - start < 5) start = cursor - 5;
      if (start < 0) start = 0;

      break;

    case CSKEY_RIGHT:
      if (cursor < text->Length ()) {
        cursor++;
      }

      break;

    case CSKEY_HOME:
      cursor=0;
      start=0;

      break;

    case CSKEY_END:
      cursor=text->Length();

      break;

    default:
      {
	if (!isprint (Char))
	  break;

	if (disallow && (strchr (disallow->GetData (), Char) != 0))
	  break;

	char str[2];
	str[0] = (char)Char;
	str[1] = 0;
        scfString tmp(str);

        if (cursor == text->Length ())
        {
	  text->Append (str);
        }
        else
        {
          text->Insert (cursor, &tmp);
        }
	cursor++;
	Broadcast (signalChanged);
      }
  }         // end switch
  Invalidate ();
  return true;
}

bool awsTextBox::OnLostFocus ()
{
  has_focus = false;
  Broadcast (signalLostFocus);
  Invalidate ();
  return true;
}

bool awsTextBox::OnGainFocus ()
{
  has_focus = true;
  Invalidate ();
  return true;
}

void awsTextBox::OnSetFocus ()
{
	Broadcast (signalFocused);
}

/************************************* Command Button Factory ****************/
awsTextBoxFactory::awsTextBoxFactory (iAws *wmgr) :
  awsComponentFactory(wmgr)
{
  Register ("Text Box");
  RegisterConstant ("tbfsNormal", awsTextBox::fsNormal);
  RegisterConstant ("tbfsBitmap", awsTextBox::fsBitmap);

  RegisterConstant ("signalTextBoxChanged", awsTextBox::signalChanged);
  RegisterConstant ("signalTextBoxLostFocus", awsTextBox::signalLostFocus);
  RegisterConstant ("signalEnterKeyPressed", awsTextBox::signalEnterPressed);
  RegisterConstant ("signalTabKeyPressed", awsTextBox::signalTabPressed);
  RegisterConstant ("signalTextBoxFocused", awsTextBox::signalFocused);
}

awsTextBoxFactory::~awsTextBoxFactory ()
{
  // empty
}

iAwsComponent *awsTextBoxFactory::Create ()
{
  return new awsTextBox;
}
<commit_msg>Added property "Focusable"<commit_after>#include "cssysdef.h"

#include <ctype.h>

#include "awstimer.h"
#include "awstxtbx.h"
#include "ivideo/graph2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "csutil/scfstr.h"
#include "iutil/evdefs.h"

#include <stdio.h>

const int awsTextBox::fsNormal = 0x0;
const int awsTextBox::fsBitmap = 0x1;

const int awsTextBox::signalChanged = 0x1;
const int awsTextBox::signalLostFocus = 0x2;
const int awsTextBox::signalEnterPressed = 0x3;
const int awsTextBox::signalTabPressed = 0x4;
const int awsTextBox::signalFocused = 0x5;

static iAwsSink *textbox_sink = 0;

CS_IMPLEMENT_STATIC_VAR (GetTextBoxBlinkingCursorSlot, awsSlot,())

static awsSlot *textbox_slot = NULL;

static void BlinkCursor (void *, iAwsSource *source)
{
  iAwsComponent *comp = source->GetComponent ();

  //  Setting blink actually forces an inversion of blink's property, and if the textbox is the

  // focus then it will be Invalidated as well.
  comp->SetProperty ("Blink", 0);
}

awsTextBox::awsTextBox () :
  mouse_is_over(false),
  has_focus(false),
  should_mask(0),
  bkg(NULL),
  frame_style(0),
  alpha_level(92),
  text(NULL),
  disallow(NULL),
  maskchar(NULL),
  start(0),
  cursor(0),
  blink_timer(NULL),
  blink(true)
{
  textbox_slot = GetTextBoxBlinkingCursorSlot ();
}

awsTextBox::~awsTextBox ()
{
  if (blink_timer != 0)
  {
    textbox_slot->Disconnect (
        blink_timer,
        awsTimer::signalTick,
        textbox_sink,
        textbox_sink->GetTriggerID ("Blink"));
    delete blink_timer;
  }
}

const char *awsTextBox::Type ()
{
  return "Text Box";
}

bool awsTextBox::Setup (iAws *_wmgr, iAwsComponentNode *settings)
{
  if (!awsComponent::Setup (_wmgr, settings)) return false;

  // Setup blink event handling
  if (textbox_sink == 0)
  {
    textbox_sink = WindowManager ()->GetSinkMgr ()->CreateSink (NULL);
    textbox_sink->RegisterTrigger ("Blink", &BlinkCursor);
  }

  blink_timer = new awsTimer (WindowManager ()->GetObjectRegistry (), this);
  blink_timer->SetTimer (350);
  blink_timer->Start ();

  textbox_slot->Connect (
      blink_timer,
      awsTimer::signalTick,
      textbox_sink,
      textbox_sink->GetTriggerID ("Blink"));

  ////////////////
  iAwsPrefManager *pm = WindowManager ()->GetPrefMgr ();

  pm->LookupIntKey ("ButtonTextureAlpha", alpha_level); // global get
  pm->GetInt (settings, "Style", frame_style);
  pm->GetInt (settings, "Alpha", alpha_level);          // local overrides, if present.
  pm->GetInt (settings, "Masked", should_mask);
  pm->GetString (settings, "Text", text);
  pm->GetString (settings, "Disallow", disallow);
  pm->GetString (settings, "MaskChar", maskchar);

  int _focusable = 0;
  pm->GetInt (settings, "Focusable", _focusable);
	focusable = _focusable;

	if (text) {
      cursor = text->Length ();
      text = new scfString(*text);
  } else
    text = new scfString ();

  switch (frame_style)
  {
    case fsNormal:
      bkg = pm->GetTexture ("Texture");
      break;

    case fsBitmap:
      {
        iString *tn1 = NULL;

        pm->GetString (settings, "Bitmap", tn1);

        if (tn1) bkg = pm->GetTexture (tn1->GetData (), tn1->GetData ());
      }
      break;
  }

  return true;
}

bool awsTextBox::GetProperty (const char *name, void **parm)
{
  if (awsComponent::GetProperty (name, parm)) return true;

  if (strcmp ("Text", name) == 0)
  {
    char *st = NULL;

    if (text) st = text->GetData ();

    iString *s = new scfString (st);
    *parm = (void *)s;
    return true;
  }
  else if (strcmp ("Disallow", name) == 0)
  {
    char *st = NULL;

    if (disallow) st = disallow->GetData ();

    iString *s = new scfString (st);
    *parm = (void *)s;
    return true;
  }

  return false;
}

bool awsTextBox::SetProperty (const char *name, void *parm)
{
  if (awsComponent::SetProperty (name, parm)) return true;

  if (strcmp ("Blink", name) == 0)
  {
    blink = !blink;
    if (has_focus) Invalidate ();
    return true;
  }
  else if (strcmp ("Text", name) == 0)
  {
    iString *s = (iString *) (parm);

    if (s)
    {
      if (text) text->DecRef ();
      text = s;
      text->IncRef ();
      Invalidate ();
      start = 0;
      cursor = 0;
    }

    return true;
  }
  else if (strcmp ("Disallow", name) == 0)
  {
    iString *s = (iString *) (parm);

    if (s)
    {
      if (disallow) disallow->DecRef ();
      disallow = s;
      disallow->IncRef ();
    }

    return true;
  }

  return false;
}

void awsTextBox::OnDraw (csRect /*clip*/)
{
  iGraphics2D *g2d = WindowManager ()->G2D ();
  iGraphics3D *g3d = WindowManager ()->G3D ();

  int hi = WindowManager ()->GetPrefMgr ()->GetColor (AC_HIGHLIGHT);
  int hi2 = WindowManager ()->GetPrefMgr ()->GetColor (AC_HIGHLIGHT2);
  int lo = WindowManager ()->GetPrefMgr ()->GetColor (AC_SHADOW);
  int lo2 = WindowManager ()->GetPrefMgr ()->GetColor (AC_SHADOW2);
  int dfill = WindowManager ()->GetPrefMgr ()->GetColor (AC_DARKFILL);
  int black = WindowManager ()->GetPrefMgr ()->GetColor (AC_BLACK);

  switch (frame_style)
  {
    case fsNormal:
      g2d->DrawLine (
          Frame ().xmin + 0,
          Frame ().ymin + 0,
          Frame ().xmax - 1,
          Frame ().ymin + 0,
          lo2);
      g2d->DrawLine (
          Frame ().xmin + 0,
          Frame ().ymin + 0,
          Frame ().xmin + 0,
          Frame ().ymax - 1,
          lo2);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymin + 1,
          Frame ().xmax - 0,
          Frame ().ymin + 1,
          lo);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymin + 1,
          Frame ().xmin + 1,
          Frame ().ymax - 0,
          lo);
      g2d->DrawLine (
          Frame ().xmin + 1,
          Frame ().ymax - 0,
          Frame ().xmax - 0,
          Frame ().ymax - 0,
          hi);
      g2d->DrawLine (
          Frame ().xmax - 0,
          Frame ().ymin + 1,
          Frame ().xmax - 0,
          Frame ().ymax - 0,
          hi);

      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymin + 2,
          Frame ().xmax - 1,
          Frame ().ymin + 2,
          black);
      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymin + 2,
          Frame ().xmin + 2,
          Frame ().ymax - 1,
          black);
      g2d->DrawLine (
          Frame ().xmin + 2,
          Frame ().ymax - 1,
          Frame ().xmax - 1,
          Frame ().ymax - 1,
          hi2);
      g2d->DrawLine (
          Frame ().xmax - 1,
          Frame ().ymin + 2,
          Frame ().xmax - 1,
          Frame ().ymax - 1,
          hi2);

      g2d->DrawBox (
          Frame ().xmin + 3,
          Frame ().ymin + 3,
          Frame ().Width () - 3,
          Frame ().Height () - 3,
          dfill);

      if (bkg)
      {
        g3d->DrawPixmap (
            bkg,
            Frame ().xmin,
            Frame ().ymin,
            Frame ().Width () + 1,
            Frame ().Height () + 1,
            0,
            0,
            Frame ().Width () + 1,
            Frame ().Height () + 1,
            alpha_level);
      }
      break;

    case fsBitmap:
      if (bkg)
      {
        g3d->DrawPixmap (
            bkg,
            Frame ().xmin,
            Frame ().ymin,
            Frame ().Width (),
            Frame ().Height (),
            0,
            0,
            Frame ().Width (),
            Frame ().Height (),
            alpha_level);
      }
      break;
  }

  // Draw the caption, if there is one and the style permits it.
  if (text && text->Length ())
  {
    int tw, th, tx, ty, mcc;
    iString *saved = NULL;

    if (should_mask && maskchar)
    {
      saved = text->Clone ();

      unsigned int i;
      for (i = 0; i < text->Length (); ++i)
        text->SetAt (i, maskchar->GetAt (0));
    }

    // Get the maximum number of characters we can use
    mcc = WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->GetLength (
        text->GetData () + start,
        Frame ().Width () - 10);

    if (mcc)
    {

      // Check to see if we're getting weird.
      // this was changed to avoid
      // jittering in the start value
      if ((int)cursor > start + mcc) start = cursor - mcc;
      if (start < 0) start = 0;

      // Make the text the right length
      scfString tmp (text->GetData () + start);
      tmp.Truncate (mcc);

      // Get the size of the text
      WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
          GetDimensions (tmp.GetData (), tw, th);

      // Calculate the center
      tx = 4;
      ty = (Frame ().Height () >> 1) - (th >> 1);

      // Draw the text
      g2d->Write (
      WindowManager ()->GetPrefMgr ()->GetDefaultFont (),
      Frame ().xmin + tx,
      Frame ().ymin + ty,
      WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE),
      -1,
      tmp.GetData ());

      if (should_mask && maskchar && saved)
      {
    text->Clear ();
    text->Append (saved);
    saved->Clear ();
    saved->DecRef ();
      }

    if (has_focus && blink)
    {
      int co, cx, tty;
      co = cursor - start;
      tmp.Truncate (co);
      // figure out where to put the cursor
      WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
         GetDimensions (tmp, cx, tty);
      g2d->DrawLine (
          Frame ().xmin + tx + cx + 1,
          Frame ().ymin + ty,
          Frame ().xmin + tx + cx + 1,
          Frame ().ymin + ty + th,
          WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE));
    }
    }
  }
  else if (has_focus && blink)
  {
    g2d->DrawLine (
        Frame ().xmin + 5,
        Frame ().ymin + 5,
        Frame ().xmin + 5,
        Frame ().ymax - 5,
        WindowManager ()->GetPrefMgr ()->GetColor (AC_TEXTFORE));
  }
}

bool awsTextBox::OnMouseDown (int, int x, int y)
{
  // make sure text is valid
  if (text && text->Length() > 0)
  {
    // determine how many chars in the mouse was clicked
    int tp,cp;
    scfString tmp(text->GetData () + start);
    tp = x - 4 - Frame ().xmin;
    cp = WindowManager ()->GetPrefMgr ()->GetDefaultFont ()->
      GetLength(tmp,tp);
    cursor = cp + start;
  }
  // This is needed to get keyboard focus for the mouse!
  return true;
}

bool awsTextBox::OnMouseExit ()
{
  mouse_is_over = false;
  Invalidate ();
  return true;
}

bool awsTextBox::OnMouseEnter ()
{
  mouse_is_over = true;
  Invalidate ();
  return true;
}

bool awsTextBox::OnKeypress (int key, int Char, int)
{
  switch (key)
  {
    case CSKEY_ENTER:
      Broadcast (signalEnterPressed);
      break;

    case CSKEY_TAB:
      Broadcast (signalTabPressed);
      break;

    case CSKEY_BACKSPACE:
      if (cursor > 0)
      {
        cursor--;
        if (cursor - start < 5) start = cursor - 5;
        if (start < 0) start = 0;
        if (text && (text->Length () > 1))
          if (cursor == text->Length ())
            text->Truncate (text->Length () - 1);
          else
          {
            scfString tmp(text->GetData());
            tmp.Truncate (cursor);
            tmp.Append (text->GetData()+cursor+1);
            text->Replace(&tmp);
          }
        else
          text->Clear ();
      }

      break;

    case CSKEY_DEL:
      if (cursor > 0 && cursor == text->Length ()) cursor--;
      if (cursor - start < 5) start = cursor - 5;
      if (start < 0) start = 0;
      if (text && (text->Length () > 1))
        if (cursor == text->Length ())
          text->Truncate (text->Length () - 1);
        else
        {
          scfString tmp(text->GetData());
          tmp.Truncate (cursor);
          tmp.Append (text->GetData()+cursor+1);
          text->Replace(&tmp);
        }
      else
        text->Clear ();

      break;

    case CSKEY_LEFT:
      if (cursor > 0) cursor--;
      if (cursor - start < 5) start = cursor - 5;
      if (start < 0) start = 0;

      break;

    case CSKEY_RIGHT:
      if (cursor < text->Length ()) {
        cursor++;
      }

      break;

    case CSKEY_HOME:
      cursor=0;
      start=0;

      break;

    case CSKEY_END:
      cursor=text->Length();

      break;

    default:
      {
	if (!isprint (Char))
	  break;

	if (disallow && (strchr (disallow->GetData (), Char) != 0))
	  break;

	char str[2];
	str[0] = (char)Char;
	str[1] = 0;
        scfString tmp(str);

        if (cursor == text->Length ())
        {
	  text->Append (str);
        }
        else
        {
          text->Insert (cursor, &tmp);
        }
	cursor++;
	Broadcast (signalChanged);
      }
  }         // end switch
  Invalidate ();
  return true;
}

bool awsTextBox::OnLostFocus ()
{
  has_focus = false;
  Broadcast (signalLostFocus);
  Invalidate ();
  return true;
}

bool awsTextBox::OnGainFocus ()
{
  has_focus = true;
  Invalidate ();
  return true;
}

void awsTextBox::OnSetFocus ()
{
	Broadcast (signalFocused);
}

/************************************* Command Button Factory ****************/
awsTextBoxFactory::awsTextBoxFactory (iAws *wmgr) :
  awsComponentFactory(wmgr)
{
  Register ("Text Box");
  RegisterConstant ("tbfsNormal", awsTextBox::fsNormal);
  RegisterConstant ("tbfsBitmap", awsTextBox::fsBitmap);

  RegisterConstant ("signalTextBoxChanged", awsTextBox::signalChanged);
  RegisterConstant ("signalTextBoxLostFocus", awsTextBox::signalLostFocus);
  RegisterConstant ("signalEnterKeyPressed", awsTextBox::signalEnterPressed);
  RegisterConstant ("signalTabKeyPressed", awsTextBox::signalTabPressed);
  RegisterConstant ("signalTextBoxFocused", awsTextBox::signalFocused);
}

awsTextBoxFactory::~awsTextBoxFactory ()
{
  // empty
}

iAwsComponent *awsTextBoxFactory::Create ()
{
  return new awsTextBox;
}
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_instance.cpp implementation of the GLC_Instance class.

#include "glc_instance.h"
#include "glc_selectionmaterial.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_Instance::GLC_Instance()
: m_pGeom(NULL)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	//qDebug() << "GLC_Instance::GLC_Instance null instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Contruct instance with a geometry
GLC_Instance::GLC_Instance(GLC_Geometry* pGeom)
: m_pGeom(pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	setName(pGeom->getName());
	//qDebug() << "GLC_Instance::GLC_Instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Copy constructor
GLC_Instance::GLC_Instance(const GLC_Instance& inputNode)
: GLC_Object(inputNode)
, m_pGeom(inputNode.m_pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(inputNode.m_pNumberOfInstance)
, m_MatPos(inputNode.m_MatPos)
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(inputNode.m_PolyFace)
, m_PolyMode(inputNode.m_PolyMode)
, m_IsVisible(inputNode.m_IsVisible)

{
	// Increment the number of instance
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::GLC_Instance CopyConstructor ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Assignement operator
GLC_Instance& GLC_Instance::operator=(const GLC_Instance& inputNode)
{

	clear();
	m_pGeom= inputNode.m_pGeom;
	m_Uid= inputNode.m_Uid;
	m_Name= inputNode.m_Name;

	m_pNumberOfInstance= inputNode.m_pNumberOfInstance;
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::operator= :ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
	m_MatPos= inputNode.m_MatPos;
	return *this;
}

// Destructor
GLC_Instance::~GLC_Instance()
{
	clear();
}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Get the geometry of the instance
GLC_Geometry* GLC_Instance::getGeometry(void)
{
	return m_pGeom;
}

// Get the validity of the OpenGL list
const bool GLC_Instance::getValidity(void) const
{
	if ((m_pGeom != NULL) && (m_IsValid))
	{
		return m_pGeom->getValidity();
	}
	else return false;
}

// Get the bounding box
GLC_BoundingBox GLC_Instance::getBoundingBox(void)
{
	if (getBoundingBoxValidity())
	{
		return *m_pBoundingBox;
	}
	else if (m_pGeom != NULL)
	{
		computeBoundingBox();
		if (m_pBoundingBox != NULL)
		{
			return *m_pBoundingBox;
		}

	}

	GLC_BoundingBox nullBoundingBox;
	return nullBoundingBox;
}

// Get the validity of the Bounding Box
const bool GLC_Instance::getBoundingBoxValidity(void) const
{
	if ((m_pGeom != NULL) && (m_pBoundingBox != NULL))
	{
		return (m_pGeom->getListIsValid()) && (m_pGeom->getValidity());
	}
	else return false;
}

// Clone the instance
GLC_Instance GLC_Instance::clone() const
{
	GLC_Instance cloneInstance;
	cloneInstance.m_pGeom= m_pGeom->clone();
	if (NULL != m_pBoundingBox)
	{
		cloneInstance.m_pBoundingBox= new GLC_BoundingBox(*m_pBoundingBox);
	}
	cloneInstance.m_MatPos= m_MatPos;
	cloneInstance.m_PolyFace= m_PolyFace;
	cloneInstance.m_PolyMode= m_PolyMode;
	return cloneInstance;
}

// Instanciate the instance
GLC_Instance GLC_Instance::instanciate()
{
	GLC_Instance instance(*this);
	instance.m_Uid= glc::GLC_GenID();
	return instance;
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set the instance Geometry
bool GLC_Instance::setGeometry(GLC_Geometry* pGeom)
{
		if (NULL == m_pGeom) return false;
		else
		{
			m_pGeom= pGeom;
			return true;
		}
}

// Geometry translation
void GLC_Instance::translate(double Tx, double Ty, double Tz)
{
	GLC_Matrix4x4 MatTrans(Tx, Ty, Tz);

	multMatrix(MatTrans);
}

// move instance with a 4x4Matrix
void GLC_Instance::multMatrix(const GLC_Matrix4x4 &MultMat)
{
	m_MatPos= MultMat * m_MatPos;

	m_IsValid= false;
}

// Replace the instance Matrix
void GLC_Instance::setMatrix(const GLC_Matrix4x4 &SetMat)
{
	m_MatPos= SetMat;

	m_IsValid= false;
}

// Reset the instance Matrix
void GLC_Instance::resetMatrix(void)
{
	m_MatPos.setToIdentity();

	m_IsValid= false;
}

// Polygon's display style
void GLC_Instance::setPolygonMode(GLenum Face, GLenum Mode)
{
	// Change the polygon mode only if there is a change
	if ((m_PolyFace != Face) || (m_PolyMode != Mode))
	{
		m_PolyFace= Face;
		m_PolyMode= Mode;
		m_IsValid = false;
	}
}

// Select the instance
void GLC_Instance::select(void)
{
	m_IsSelected= true;
	m_IsValid= false;
}

// Unselect the instance
void GLC_Instance::unselect(void)
{
	m_IsSelected= false;
	m_IsValid= false;
}

// set Instance validity in case of multiple instance.
void GLC_Instance::setInstanceValidity(void)
{
	if ((m_pGeom != NULL) && (m_IsValid))
	{
		m_IsValid= m_pGeom->getValidity();
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Display the instance
void GLC_Instance::glExecute(GLenum Mode)
{
	bool computeBox= false;
	if (NULL == m_pGeom) return;
	// Geometry OpenGl list invalid
	if (!m_pGeom->getListIsValid())
	{
		m_pGeom->glLoadTexture();
		m_pGeom->createList(GL_COMPILE);
		computeBox= true;
	}

	// Geometry invalid or instance
	if ((!m_pGeom->getValidity()) || (!m_IsValid))
	{
		m_IsValid= true;
		computeBox= true;
	}
	// Object ID for selection purpose
	glLoadName(getID());
	// Save current OpenGL Matrix
	glPushMatrix();
	glVisProperties();
	m_pGeom->glExecute(Mode, m_IsSelected, ((m_PolyMode != GL_FILL)));
	// Restore OpenGL Matrix
	glPopMatrix();
	//qDebug() << "GLC_Instance::GlExecute : Display list " << m_ListID << " created";

	if (computeBox)
	{
		computeBoundingBox();
	}

}

// Set instance visualisation properties
void GLC_Instance::glVisProperties()
{
	// Polygons display mode
	glPolygonMode(m_PolyFace, m_PolyMode);
	// Change the current matrix
	glMultMatrixd(m_MatPos.return_dMat());

}

//////////////////////////////////////////////////////////////////////
// private services functions
//////////////////////////////////////////////////////////////////////

// compute the instance bounding box
// m_pGeom should be not null
void GLC_Instance::computeBoundingBox(void)
{
	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	m_pBoundingBox= m_pGeom->getBoundingBox();
	m_pBoundingBox->transform(m_MatPos);

}

// Clear current instance
void GLC_Instance::clear()
{
	Q_ASSERT(m_pNumberOfInstance != NULL);

	if ((--(*m_pNumberOfInstance)) == 0)
	{
		// this is the last instance, delete the geometry
		if (m_pGeom != NULL)
		{
			delete m_pGeom;
			m_pGeom= NULL;
		}
		// delete instance counter
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << "- Number of instance" << (*m_pNumberOfInstance);
		delete m_pNumberOfInstance;
		m_pNumberOfInstance= NULL;

	}
	else
	{
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << " - Number of instance" << (*m_pNumberOfInstance);
	}

	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	// invalidate the instance
	m_IsValid= false;

}

<commit_msg>before returning bounding box validity, just test the geometry validity. (List validity is include in geometry validity).<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.0.0, packaged on August, 2008.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_instance.cpp implementation of the GLC_Instance class.

#include "glc_instance.h"
#include "glc_selectionmaterial.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_Instance::GLC_Instance()
: m_pGeom(NULL)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	//qDebug() << "GLC_Instance::GLC_Instance null instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Contruct instance with a geometry
GLC_Instance::GLC_Instance(GLC_Geometry* pGeom)
: m_pGeom(pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(new int(1))
, m_MatPos()
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(GL_FRONT_AND_BACK)
, m_PolyMode(GL_FILL)
, m_IsVisible(true)
{
	setName(pGeom->getName());
	//qDebug() << "GLC_Instance::GLC_Instance ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Copy constructor
GLC_Instance::GLC_Instance(const GLC_Instance& inputNode)
: GLC_Object(inputNode)
, m_pGeom(inputNode.m_pGeom)
, m_pBoundingBox(NULL)
, m_pNumberOfInstance(inputNode.m_pNumberOfInstance)
, m_MatPos(inputNode.m_MatPos)
, m_IsValid(false)
, m_IsSelected(false)
, m_PolyFace(inputNode.m_PolyFace)
, m_PolyMode(inputNode.m_PolyMode)
, m_IsVisible(inputNode.m_IsVisible)

{
	// Increment the number of instance
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::GLC_Instance CopyConstructor ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
}

// Assignement operator
GLC_Instance& GLC_Instance::operator=(const GLC_Instance& inputNode)
{

	clear();
	m_pGeom= inputNode.m_pGeom;
	m_Uid= inputNode.m_Uid;
	m_Name= inputNode.m_Name;

	m_pNumberOfInstance= inputNode.m_pNumberOfInstance;
	++(*m_pNumberOfInstance);
	//qDebug() << "GLC_Instance::operator= :ID = " << m_Uid;
	//qDebug() << "Number of instance" << (*m_pNumberOfInstance);
	m_MatPos= inputNode.m_MatPos;
	return *this;
}

// Destructor
GLC_Instance::~GLC_Instance()
{
	clear();
}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Get the geometry of the instance
GLC_Geometry* GLC_Instance::getGeometry(void)
{
	return m_pGeom;
}

// Get the validity of the OpenGL list
const bool GLC_Instance::getValidity(void) const
{
	if ((m_pGeom != NULL) && (m_IsValid))
	{
		return m_pGeom->getValidity();
	}
	else return false;
}

// Get the bounding box
GLC_BoundingBox GLC_Instance::getBoundingBox(void)
{
	if (getBoundingBoxValidity())
	{
		return *m_pBoundingBox;
	}
	else if (m_pGeom != NULL)
	{
		computeBoundingBox();
		if (m_pBoundingBox != NULL)
		{
			return *m_pBoundingBox;
		}

	}

	GLC_BoundingBox nullBoundingBox;
	return nullBoundingBox;
}

// Get the validity of the Bounding Box
const bool GLC_Instance::getBoundingBoxValidity(void) const
{
	if ((m_pGeom != NULL) && (m_pBoundingBox != NULL))
	{
		return m_pGeom->getValidity();
	}
	else return false;
}

// Clone the instance
GLC_Instance GLC_Instance::clone() const
{
	GLC_Instance cloneInstance;
	cloneInstance.m_pGeom= m_pGeom->clone();
	if (NULL != m_pBoundingBox)
	{
		cloneInstance.m_pBoundingBox= new GLC_BoundingBox(*m_pBoundingBox);
	}
	cloneInstance.m_MatPos= m_MatPos;
	cloneInstance.m_PolyFace= m_PolyFace;
	cloneInstance.m_PolyMode= m_PolyMode;
	return cloneInstance;
}

// Instanciate the instance
GLC_Instance GLC_Instance::instanciate()
{
	GLC_Instance instance(*this);
	instance.m_Uid= glc::GLC_GenID();
	return instance;
}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Set the instance Geometry
bool GLC_Instance::setGeometry(GLC_Geometry* pGeom)
{
		if (NULL == m_pGeom) return false;
		else
		{
			m_pGeom= pGeom;
			return true;
		}
}

// Geometry translation
void GLC_Instance::translate(double Tx, double Ty, double Tz)
{
	GLC_Matrix4x4 MatTrans(Tx, Ty, Tz);

	multMatrix(MatTrans);
}

// move instance with a 4x4Matrix
void GLC_Instance::multMatrix(const GLC_Matrix4x4 &MultMat)
{
	m_MatPos= MultMat * m_MatPos;

	m_IsValid= false;
}

// Replace the instance Matrix
void GLC_Instance::setMatrix(const GLC_Matrix4x4 &SetMat)
{
	m_MatPos= SetMat;

	m_IsValid= false;
}

// Reset the instance Matrix
void GLC_Instance::resetMatrix(void)
{
	m_MatPos.setToIdentity();

	m_IsValid= false;
}

// Polygon's display style
void GLC_Instance::setPolygonMode(GLenum Face, GLenum Mode)
{
	// Change the polygon mode only if there is a change
	if ((m_PolyFace != Face) || (m_PolyMode != Mode))
	{
		m_PolyFace= Face;
		m_PolyMode= Mode;
		m_IsValid = false;
	}
}

// Select the instance
void GLC_Instance::select(void)
{
	m_IsSelected= true;
	m_IsValid= false;
}

// Unselect the instance
void GLC_Instance::unselect(void)
{
	m_IsSelected= false;
	m_IsValid= false;
}

// set Instance validity in case of multiple instance.
void GLC_Instance::setInstanceValidity(void)
{
	if ((m_pGeom != NULL) && (m_IsValid))
	{
		m_IsValid= m_pGeom->getValidity();
	}
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Display the instance
void GLC_Instance::glExecute(GLenum Mode)
{
	bool computeBox= false;
	if (NULL == m_pGeom) return;

	// Geometry invalid or instance
	if ((!m_pGeom->getValidity()) || (!m_IsValid))
	{
		m_IsValid= true;
		computeBox= true;
	}
	// Object ID for selection purpose
	glLoadName(getID());
	// Save current OpenGL Matrix
	glPushMatrix();
	glVisProperties();
	m_pGeom->glExecute(Mode, m_IsSelected, ((m_PolyMode != GL_FILL)));
	// Restore OpenGL Matrix
	glPopMatrix();
	//qDebug() << "GLC_Instance::GlExecute : Display list " << m_ListID << " created";

	if (computeBox)
	{
		computeBoundingBox();
	}

}

// Set instance visualisation properties
void GLC_Instance::glVisProperties()
{
	// Polygons display mode
	glPolygonMode(m_PolyFace, m_PolyMode);
	// Change the current matrix
	glMultMatrixd(m_MatPos.return_dMat());

}

//////////////////////////////////////////////////////////////////////
// private services functions
//////////////////////////////////////////////////////////////////////

// compute the instance bounding box
// m_pGeom should be not null
void GLC_Instance::computeBoundingBox(void)
{
	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	m_pBoundingBox= m_pGeom->getBoundingBox();
	m_pBoundingBox->transform(m_MatPos);

}

// Clear current instance
void GLC_Instance::clear()
{
	Q_ASSERT(m_pNumberOfInstance != NULL);

	if ((--(*m_pNumberOfInstance)) == 0)
	{
		// this is the last instance, delete the geometry
		if (m_pGeom != NULL)
		{
			delete m_pGeom;
			m_pGeom= NULL;
		}
		// delete instance counter
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << "- Number of instance" << (*m_pNumberOfInstance);
		delete m_pNumberOfInstance;
		m_pNumberOfInstance= NULL;

	}
	else
	{
		//qDebug() << "GLC_Instance::clear ID = " << m_Uid;
		//qDebug() << " - Number of instance" << (*m_pNumberOfInstance);
	}

	if (m_pBoundingBox != NULL)
	{
		delete m_pBoundingBox;
		m_pBoundingBox= NULL;
	}

	// invalidate the instance
	m_IsValid= false;

}

<|endoftext|>


<commit_before>#include <math/Matrix4x4.h>
#include <math/Quaternion.h>
#include <math/Vector2.h>
#include <math/Vector3.h>
#include <math/Vector4.h>

#include <render/Material.h>
#include <render/Mesh.h>
#include <render/Node.h>
#include <render/Renderer.h>
#include <render/RenderTexture.h>
#include <render/SceneTree.h>
#include <render/Shader.h>
#include <render/Texture2D.h>
#include <render/Texture3D.h>

#include <system/Logger.h>
#include <system/Window.h>
#include <system/WindowEvent.h>
using namespace Sketch3D;

#include <vector>
#include <string>
#include <time.h>
using namespace std;

#ifdef OIS_AVAILABLE
#include <OIS.h>
#endif

#define NUM_LIGHTS 4

void UpdateLights(double t, Vector3 initialLightPositions[], Vector3 newLightPositions[]);

#if defined(__WIN32__) || defined(_WIN32)
#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
#else
int main(int argc, char** argv) {
#endif
    Window window("Sample_Shadow", 1024, 768, true);
    Renderer::GetInstance()->Initialize(RENDER_SYSTEM_OPENGL, window);
    Renderer::GetInstance()->SetClearColor(0.2f, 0.2f, 0.2f);

    // Create a render texture for the shadow map
    RenderTexture* shadowMaps[4];
    Texture2D* shadowMapTextures[4];

    for (size_t i = 0; i < NUM_LIGHTS; i++) {
        shadowMaps[i] = Renderer::GetInstance()->CreateRenderTexture(512, 512, TEXTURE_FORMAT_DEPTH);
        shadowMapTextures[i] = Renderer::GetInstance()->CreateTexture2D();

        shadowMapTextures[i]->SetWidth(512);
        shadowMapTextures[i]->SetHeight(512);
        shadowMapTextures[i]->SetTextureFormat(TEXTURE_FORMAT_DEPTH);
        shadowMapTextures[i]->SetFilterMode(FILTER_MODE_LINEAR);
        shadowMapTextures[i]->SetWrapMode(WRAP_MODE_CLAMP);

        if (!shadowMapTextures[i]->Create()) {
            Logger::GetInstance()->Error("Couldn't create shadow map texture");
        }

        if (!shadowMaps[i]->AttachTextureToDepthBuffer(shadowMapTextures[i])) {
            Logger::GetInstance()->Error("Couldn't create shadow map");
        }
    }

    // Create the shader
    vector<string> vertexInputs;
    vertexInputs.push_back("in_vertex");
    vertexInputs.push_back("in_normal");
    vertexInputs.push_back("in_uv");
    Shader* shader = Renderer::GetInstance()->CreateShader("Shaders/Shadow/vert.glsl", "Shaders/Shadow/frag.glsl", vertexInputs);
    Material material(shader);

    // Create the jeep
    VertexAttributesMap_t vertexAttributes;
    vertexAttributes[VERTEX_ATTRIBUTES_POSITION] = 0;
    vertexAttributes[VERTEX_ATTRIBUTES_NORMAL] = 1;
    vertexAttributes[VERTEX_ATTRIBUTES_TEX_COORDS] = 2;
    Mesh jeepMesh("Media/jeep1.3ds", vertexAttributes);
    Node jeepNode1;
    jeepNode1.SetMaterial(&material);
    jeepNode1.SetMesh(&jeepMesh);

    // The jeep mesh is not oriented correctly for our needs
    Quaternion orientation;
    orientation.MakeFromAngleAxis(-PI_OVER_2, Vector3::RIGHT);

    jeepNode1.SetOrientation(orientation);
    Renderer::GetInstance()->GetSceneTree().AddNode(&jeepNode1);

    // Create a second jeep
    Node jeepNode2;
    jeepNode2.SetMaterial(&material);
    jeepNode2.SetMesh(&jeepMesh);
    jeepNode2.SetOrientation(orientation);
    jeepNode2.SetPosition(Vector3(-15.0f, 0.0f, -12.0f));
    Renderer::GetInstance()->GetSceneTree().AddNode(&jeepNode2);

    // Create the ground
    Mesh groundMesh;

    SurfaceTriangles_t surface;
    surface.numVertices = 4;
    surface.numNormals = 4;
    surface.numTexCoords = 4;
    surface.numIndices = 6;
    surface.numTextures = 1;
    surface.vertices = new Vector3[surface.numVertices];
    surface.normals = new Vector3[surface.numNormals];
    surface.texCoords = new Vector2[surface.numTexCoords];
    surface.indices = new unsigned short[surface.numIndices];
    surface.textures = new Texture2D* [surface.numTextures];

    surface.vertices[0] = Vector3(-50.0f, 0.0f, -50.0f); surface.vertices[1] = Vector3(-50.0f, 0.0f, 50.0f); surface.vertices[2] = Vector3(50.0f, 0.0f, 50.0f); surface.vertices[3] = Vector3(50.0f, 0.0f, -50.0f);
    surface.normals[0] = surface.normals[1] = surface.normals[2] = surface.normals[3] = Vector3::UP;
    surface.texCoords[0] = Vector2(0.0f, 0.0f); surface.texCoords[1] = Vector2(0.0f, 1.0f); surface.texCoords[2] = Vector2(1.0f, 1.0f); surface.texCoords[3] = Vector2(1.0f, 0.0f);
    surface.indices[0] = 0; surface.indices[1] = 1; surface.indices[2] = 2; surface.indices[3] = 0; surface.indices[4] = 2; surface.indices[5] = 3;
    surface.textures[0] = Renderer::GetInstance()->CreateTexture2DFromFile("Media/tiled.jpg");

    ModelSurface_t groundSurface;
    groundSurface.geometry = &surface;
    groundMesh.AddSurface(groundSurface);

    groundMesh.Initialize(vertexAttributes);

    // Create the ground
    Node groundNode;
    groundNode.SetMaterial(&material);
    groundNode.SetMesh(&groundMesh);
    Renderer::GetInstance()->GetSceneTree().AddNode(&groundNode);

    // Define some useful vectors for this sample
    Vector3 cameraPosition(-20.0f, 15.0f, -55.0f);

    // Defines the lights that we have
    Vector3 lightPositions[4];
    Vector4 lightColors[4];
    Vector3 newLightPositions[4];

    newLightPositions[0] = lightPositions[0] = Vector3(15.0f, 20.0f, 15.0f);
    newLightPositions[1] = lightPositions[1] = Vector3(-40.0f, 15.0f, -30.0f);
    newLightPositions[2] = lightPositions[2] = Vector3(15.0f, 30.0f, -20.0f);
    newLightPositions[3] = lightPositions[3] = Vector3(-20.0f, 15.0f, 20.0f);
    lightColors[0] = Vector4(1.0f, 1.0f, 1.0f, 100.0f);
    lightColors[1] = Vector4(0.8f, 0.0f, 0.0f, 100.0f);
    lightColors[2] = Vector4(0.0f, 0.8f, 0.0f, 100.0f);
    lightColors[3] = Vector4(0.0f, 0.0f, 0.8f, 100.0f);

    Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.5f,
                         0.0f, 0.5f, 0.0f, 0.5f,
                         0.0f, 0.0f, 0.5f, 0.5f,
                         0.0f, 0.0f, 0.0f, 1.0f);

    Renderer::GetInstance()->SetBlendingFactor(BLENDING_FACTOR_ONE, BLENDING_FACTOR_ONE);

    double t = 0.0;
    clock_t begin;
    clock_t end;

    // Initialize OIS if available
#ifdef OIS_AVAILABLE
    size_t windowHandle = (size_t)window.GetHandle();

    OIS::ParamList paramList;
    paramList.insert(pair<string, string>("WINDOW", to_string(windowHandle)));
    OIS::InputManager* inputManager = OIS::InputManager::createInputSystem(paramList);

    OIS::Keyboard* keyboard = static_cast<OIS::Keyboard*>(inputManager->createInputObject(OIS::OISKeyboard, false));
#endif

    size_t currentLightNumber = 1;

    while (window.IsOpen()) {
        begin = clock();

        WindowEvent windowEvent;
        if (window.PollEvents(windowEvent)) {
        }

        // Movement & change the number of lights
#ifdef OIS_AVAILABLE
        keyboard->capture();

        if (keyboard->isKeyDown(OIS::KC_1)) {
            currentLightNumber = 1;
        } else if (keyboard->isKeyDown(OIS::KC_2)) {
            currentLightNumber = 2;
        } else if (keyboard->isKeyDown(OIS::KC_3)) {
            currentLightNumber = 3;
        } else if (keyboard->isKeyDown(OIS::KC_4)) {
            currentLightNumber = 4;
        }
#endif

        Renderer::GetInstance()->EnableDepthWrite(true);
        Renderer::GetInstance()->SetDepthComparisonFunc(DEPTH_FUNC_LESS);

        // Update the lights' positions
        UpdateLights(t, lightPositions, newLightPositions);

        // First, we render from each light's perspective and record the depth in their respective shadow map
        Renderer::GetInstance()->SetCullingMethod(CULLING_METHOD_FRONT_FACE);
        shader->SelectSubroutine("recordDepth", SHADER_TYPE_FRAGMENT);

        for (size_t i = 0; i < currentLightNumber; i++) {
            shadowMaps[i]->Bind();
            Renderer::GetInstance()->PerspectiveProjection(65.0f, 1024.0f/768.0f, 1.0f, 1000.0f);
            Renderer::GetInstance()->CameraLookAt(newLightPositions[i], Vector3::ZERO, Vector3::UP);
            Renderer::GetInstance()->Clear();
            Renderer::GetInstance()->Render();
        }

        // Then we use the shadow maps to render the scene normally from the camera's perspective
        Renderer::GetInstance()->BindScreenBuffer();
        Renderer::GetInstance()->Clear();
        shader->SelectSubroutine("shadeWithShadow", SHADER_TYPE_FRAGMENT);
        Renderer::GetInstance()->SetCullingMethod(CULLING_METHOD_BACK_FACE);

        for (size_t i = 0; i < currentLightNumber; i++) {
            // If there's more than one light, we activate additive blending to accumulate each light contribution in
            // the framebuffer. Moreover, we disable depth writing and set the depth comparison function to less or equal
            // to prevent Z-fighting.
            if (i == 1) {
                Renderer::GetInstance()->EnableDepthWrite(false);
                Renderer::GetInstance()->SetDepthComparisonFunc(DEPTH_FUNC_EQUAL);
                Renderer::GetInstance()->EnableBlending(true);
            }

            Renderer::GetInstance()->CameraLookAt(newLightPositions[i], Vector3::ZERO, Vector3::UP);
            Matrix4x4 shadowMatrix = biasMatrix * Renderer::GetInstance()->GetViewProjectionMatrix();
            shader->SetUniformMatrix4x4("shadowMatrix", shadowMatrix);
            shader->SetUniformVector3("light_position", newLightPositions[i]);
            shader->SetUniformVector4("light_color", lightColors[i]);
            material.AddTexture("shadowMap", shadowMapTextures[i]);

            Renderer::GetInstance()->CameraLookAt(cameraPosition, Vector3::ZERO, Vector3::UP);
            Renderer::GetInstance()->Render();
        }

        Renderer::GetInstance()->EndRender();

        if (currentLightNumber > 1) {
            Renderer::GetInstance()->EnableBlending(false);
        }

        end = clock();
        t += double(end - begin) / CLOCKS_PER_SEC;
    }

    return 0;
}

void UpdateLights(double t, Vector3 initialLightPositions[], Vector3 newLightPositions[]) {
    for (size_t i = 0; i < NUM_LIGHTS; i++) {
        float direction = (i % 2 == 0) ? 1.0f : -1.0f;
        newLightPositions[i].x = 75.0f * float(cos(direction * t / (i + 1)));
        newLightPositions[i].z = 75.0f * float(sin(direction * t / (i + 1)));
    }
}
<commit_msg>Increased resolutions of the shadow maps<commit_after>#include <math/Matrix4x4.h>
#include <math/Quaternion.h>
#include <math/Vector2.h>
#include <math/Vector3.h>
#include <math/Vector4.h>

#include <render/Material.h>
#include <render/Mesh.h>
#include <render/Node.h>
#include <render/Renderer.h>
#include <render/RenderTexture.h>
#include <render/SceneTree.h>
#include <render/Shader.h>
#include <render/Texture2D.h>
#include <render/Texture3D.h>

#include <system/Logger.h>
#include <system/Window.h>
#include <system/WindowEvent.h>
using namespace Sketch3D;

#include <vector>
#include <string>
#include <time.h>
using namespace std;

#ifdef OIS_AVAILABLE
#include <OIS.h>
#endif

#define NUM_LIGHTS 4

void UpdateLights(double t, Vector3 initialLightPositions[], Vector3 newLightPositions[]);

#if defined(__WIN32__) || defined(_WIN32)
#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
#else
int main(int argc, char** argv) {
#endif
    Window window("Sample_Shadow", 1024, 768, true);
    Renderer::GetInstance()->Initialize(RENDER_SYSTEM_OPENGL, window);
    Renderer::GetInstance()->SetClearColor(0.2f, 0.2f, 0.2f);

    // Create a render texture for the shadow map
    RenderTexture* shadowMaps[4];
    Texture2D* shadowMapTextures[4];

    for (size_t i = 0; i < NUM_LIGHTS; i++) {
        shadowMaps[i] = Renderer::GetInstance()->CreateRenderTexture(1024, 1024, TEXTURE_FORMAT_DEPTH);
        shadowMapTextures[i] = Renderer::GetInstance()->CreateTexture2D();

        shadowMapTextures[i]->SetWidth(1024);
        shadowMapTextures[i]->SetHeight(1024);
        shadowMapTextures[i]->SetTextureFormat(TEXTURE_FORMAT_DEPTH);
        shadowMapTextures[i]->SetFilterMode(FILTER_MODE_LINEAR);
        shadowMapTextures[i]->SetWrapMode(WRAP_MODE_CLAMP);

        if (!shadowMapTextures[i]->Create()) {
            Logger::GetInstance()->Error("Couldn't create shadow map texture");
        }

        if (!shadowMaps[i]->AttachTextureToDepthBuffer(shadowMapTextures[i])) {
            Logger::GetInstance()->Error("Couldn't create shadow map");
        }
    }

    // Create the shader
    vector<string> vertexInputs;
    vertexInputs.push_back("in_vertex");
    vertexInputs.push_back("in_normal");
    vertexInputs.push_back("in_uv");
    Shader* shader = Renderer::GetInstance()->CreateShader("Shaders/Shadow/vert.glsl", "Shaders/Shadow/frag.glsl", vertexInputs);
    Material material(shader);

    // Create the jeep
    VertexAttributesMap_t vertexAttributes;
    vertexAttributes[VERTEX_ATTRIBUTES_POSITION] = 0;
    vertexAttributes[VERTEX_ATTRIBUTES_NORMAL] = 1;
    vertexAttributes[VERTEX_ATTRIBUTES_TEX_COORDS] = 2;
    Mesh jeepMesh("Media/jeep1.3ds", vertexAttributes);
    Node jeepNode1;
    jeepNode1.SetMaterial(&material);
    jeepNode1.SetMesh(&jeepMesh);

    // The jeep mesh is not oriented correctly for our needs
    Quaternion orientation;
    orientation.MakeFromAngleAxis(-PI_OVER_2, Vector3::RIGHT);

    jeepNode1.SetOrientation(orientation);
    Renderer::GetInstance()->GetSceneTree().AddNode(&jeepNode1);

    // Create a second jeep
    Node jeepNode2;
    jeepNode2.SetMaterial(&material);
    jeepNode2.SetMesh(&jeepMesh);
    jeepNode2.SetOrientation(orientation);
    jeepNode2.SetPosition(Vector3(-15.0f, 0.0f, -12.0f));
    Renderer::GetInstance()->GetSceneTree().AddNode(&jeepNode2);

    // Create the ground
    Mesh groundMesh;

    SurfaceTriangles_t surface;
    surface.numVertices = 4;
    surface.numNormals = 4;
    surface.numTexCoords = 4;
    surface.numIndices = 6;
    surface.numTextures = 1;
    surface.vertices = new Vector3[surface.numVertices];
    surface.normals = new Vector3[surface.numNormals];
    surface.texCoords = new Vector2[surface.numTexCoords];
    surface.indices = new unsigned short[surface.numIndices];
    surface.textures = new Texture2D* [surface.numTextures];

    surface.vertices[0] = Vector3(-50.0f, 0.0f, -50.0f); surface.vertices[1] = Vector3(-50.0f, 0.0f, 50.0f); surface.vertices[2] = Vector3(50.0f, 0.0f, 50.0f); surface.vertices[3] = Vector3(50.0f, 0.0f, -50.0f);
    surface.normals[0] = surface.normals[1] = surface.normals[2] = surface.normals[3] = Vector3::UP;
    surface.texCoords[0] = Vector2(0.0f, 0.0f); surface.texCoords[1] = Vector2(0.0f, 1.0f); surface.texCoords[2] = Vector2(1.0f, 1.0f); surface.texCoords[3] = Vector2(1.0f, 0.0f);
    surface.indices[0] = 0; surface.indices[1] = 1; surface.indices[2] = 2; surface.indices[3] = 0; surface.indices[4] = 2; surface.indices[5] = 3;
    surface.textures[0] = Renderer::GetInstance()->CreateTexture2DFromFile("Media/tiled.jpg");

    ModelSurface_t groundSurface;
    groundSurface.geometry = &surface;
    groundMesh.AddSurface(groundSurface);

    groundMesh.Initialize(vertexAttributes);

    // Create the ground
    Node groundNode;
    groundNode.SetMaterial(&material);
    groundNode.SetMesh(&groundMesh);
    Renderer::GetInstance()->GetSceneTree().AddNode(&groundNode);

    // Define some useful vectors for this sample
    Vector3 cameraPosition(-20.0f, 15.0f, -55.0f);

    // Defines the lights that we have
    Vector3 lightPositions[4];
    Vector4 lightColors[4];
    Vector3 newLightPositions[4];

    newLightPositions[0] = lightPositions[0] = Vector3(15.0f, 20.0f, 15.0f);
    newLightPositions[1] = lightPositions[1] = Vector3(-40.0f, 15.0f, -30.0f);
    newLightPositions[2] = lightPositions[2] = Vector3(15.0f, 30.0f, -20.0f);
    newLightPositions[3] = lightPositions[3] = Vector3(-20.0f, 15.0f, 20.0f);
    lightColors[0] = Vector4(1.0f, 1.0f, 1.0f, 100.0f);
    lightColors[1] = Vector4(0.8f, 0.0f, 0.0f, 100.0f);
    lightColors[2] = Vector4(0.0f, 0.8f, 0.0f, 100.0f);
    lightColors[3] = Vector4(0.0f, 0.0f, 0.8f, 100.0f);

    Matrix4x4 biasMatrix(0.5f, 0.0f, 0.0f, 0.5f,
                         0.0f, 0.5f, 0.0f, 0.5f,
                         0.0f, 0.0f, 0.5f, 0.5f,
                         0.0f, 0.0f, 0.0f, 1.0f);

    Renderer::GetInstance()->SetBlendingFactor(BLENDING_FACTOR_ONE, BLENDING_FACTOR_ONE);

    double t = 0.0;
    clock_t begin;
    clock_t end;

    // Initialize OIS if available
#ifdef OIS_AVAILABLE
    size_t windowHandle = (size_t)window.GetHandle();

    OIS::ParamList paramList;
    paramList.insert(pair<string, string>("WINDOW", to_string(windowHandle)));
    OIS::InputManager* inputManager = OIS::InputManager::createInputSystem(paramList);

    OIS::Keyboard* keyboard = static_cast<OIS::Keyboard*>(inputManager->createInputObject(OIS::OISKeyboard, false));
#endif

    size_t currentLightNumber = 1;

    while (window.IsOpen()) {
        begin = clock();

        WindowEvent windowEvent;
        if (window.PollEvents(windowEvent)) {
        }

        // Movement & change the number of lights
#ifdef OIS_AVAILABLE
        keyboard->capture();

        if (keyboard->isKeyDown(OIS::KC_1)) {
            currentLightNumber = 1;
        } else if (keyboard->isKeyDown(OIS::KC_2)) {
            currentLightNumber = 2;
        } else if (keyboard->isKeyDown(OIS::KC_3)) {
            currentLightNumber = 3;
        } else if (keyboard->isKeyDown(OIS::KC_4)) {
            currentLightNumber = 4;
        }
#endif

        Renderer::GetInstance()->EnableDepthWrite(true);
        Renderer::GetInstance()->SetDepthComparisonFunc(DEPTH_FUNC_LESS);

        // Update the lights' positions
        UpdateLights(t, lightPositions, newLightPositions);

        // First, we render from each light's perspective and record the depth in their respective shadow map
        Renderer::GetInstance()->SetCullingMethod(CULLING_METHOD_FRONT_FACE);
        shader->SelectSubroutine("recordDepth", SHADER_TYPE_FRAGMENT);

        for (size_t i = 0; i < currentLightNumber; i++) {
            shadowMaps[i]->Bind();
            Renderer::GetInstance()->PerspectiveProjection(65.0f, 1024.0f/768.0f, 1.0f, 1000.0f);
            Renderer::GetInstance()->CameraLookAt(newLightPositions[i], Vector3::ZERO, Vector3::UP);
            Renderer::GetInstance()->Clear();
            Renderer::GetInstance()->Render();
        }

        // Then we use the shadow maps to render the scene normally from the camera's perspective
        Renderer::GetInstance()->BindScreenBuffer();
        Renderer::GetInstance()->Clear();
        shader->SelectSubroutine("shadeWithShadow", SHADER_TYPE_FRAGMENT);
        Renderer::GetInstance()->SetCullingMethod(CULLING_METHOD_BACK_FACE);

        for (size_t i = 0; i < currentLightNumber; i++) {
            // If there's more than one light, we activate additive blending to accumulate each light contribution in
            // the framebuffer. Moreover, we disable depth writing and set the depth comparison function to less or equal
            // to prevent Z-fighting.
            if (i == 1) {
                Renderer::GetInstance()->EnableDepthWrite(false);
                Renderer::GetInstance()->SetDepthComparisonFunc(DEPTH_FUNC_EQUAL);
                Renderer::GetInstance()->EnableBlending(true);
            }

            Renderer::GetInstance()->CameraLookAt(newLightPositions[i], Vector3::ZERO, Vector3::UP);
            Matrix4x4 shadowMatrix = biasMatrix * Renderer::GetInstance()->GetViewProjectionMatrix();
            shader->SetUniformMatrix4x4("shadowMatrix", shadowMatrix);
            shader->SetUniformVector3("light_position", newLightPositions[i]);
            shader->SetUniformVector4("light_color", lightColors[i]);
            material.AddTexture("shadowMap", shadowMapTextures[i]);

            Renderer::GetInstance()->CameraLookAt(cameraPosition, Vector3::ZERO, Vector3::UP);
            Renderer::GetInstance()->Render();
        }

        Renderer::GetInstance()->EndRender();

        if (currentLightNumber > 1) {
            Renderer::GetInstance()->EnableBlending(false);
        }

        end = clock();
        t += double(end - begin) / CLOCKS_PER_SEC;
    }

    return 0;
}

void UpdateLights(double t, Vector3 initialLightPositions[], Vector3 newLightPositions[]) {
    for (size_t i = 0; i < NUM_LIGHTS; i++) {
        float direction = (i % 2 == 0) ? 1.0f : -1.0f;
        newLightPositions[i].x = 75.0f * float(cos(direction * t / (i + 1)));
        newLightPositions[i].z = 75.0f * float(sin(direction * t / (i + 1)));
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <jni.h>
#include "core/android/ApplicationAndroid.h"
#include "core/Engine.h"
#include "graphics/Renderer.h"
#include "files/FileSystem.h"
#include "input/Input.h"
#include "utils/Utils.h"

ouzel::ApplicationAndroid application;

extern "C"
{
    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_setAssetManager(JNIEnv* env, jclass cls, jobject assetManager)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::assetManager = AAssetManager_fromJava(env, assetManager);
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onSurfaceCreated(JNIEnv* env, jclass cls)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        application.run();
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onSurfaceChanged(JNIEnv* env, jclass cls, jint width, jint height)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        if (ouzel::sharedEngine)
        {
            ouzel::sharedEngine->getWindow()->setSize(ouzel::Size2(static_cast<float>(width), static_cast<float>(height)));
        }
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onDrawFrame(JNIEnv* env, jclass cls)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        if (ouzel::sharedEngine)
        {
            ouzel::sharedEngine->draw();
        }
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionDown(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchBegin(static_cast<uint64_t>(pointerId),
                                                    ouzel::sharedEngine->getRenderer()->screenToClipLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionMove(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchMove(static_cast<uint64_t>(pointerId),
                                                   ouzel::sharedEngine->getRenderer()->screenToClipLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionUp(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchEnd(static_cast<uint64_t>(pointerId),
                                                  ouzel::sharedEngine->getRenderer()->screenToClipLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionCancel(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchCancel(static_cast<uint64_t>(pointerId),
                                                     ouzel::sharedEngine->getRenderer()->screenToClipLocation(ouzel::Vector2(x, y)));
    }
}
<commit_msg>Fix Android build<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include <jni.h>
#include "core/android/ApplicationAndroid.h"
#include "core/Engine.h"
#include "graphics/Renderer.h"
#include "files/FileSystem.h"
#include "input/Input.h"
#include "utils/Utils.h"

ouzel::ApplicationAndroid application;

extern "C"
{
    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_setAssetManager(JNIEnv* env, jclass cls, jobject assetManager)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::assetManager = AAssetManager_fromJava(env, assetManager);
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onSurfaceCreated(JNIEnv* env, jclass cls)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        application.run();
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onSurfaceChanged(JNIEnv* env, jclass cls, jint width, jint height)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        if (ouzel::sharedEngine)
        {
            ouzel::sharedEngine->getWindow()->setSize(ouzel::Size2(static_cast<float>(width), static_cast<float>(height)));
        }
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_onDrawFrame(JNIEnv* env, jclass cls)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        if (ouzel::sharedEngine)
        {
            ouzel::sharedEngine->draw();
        }
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionDown(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchBegin(static_cast<uint64_t>(pointerId),
                                                    ouzel::sharedEngine->getRenderer()->screenToNormalizedLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionMove(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchMove(static_cast<uint64_t>(pointerId),
                                                   ouzel::sharedEngine->getRenderer()->screenToNormalizedLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionUp(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchEnd(static_cast<uint64_t>(pointerId),
                                                  ouzel::sharedEngine->getRenderer()->screenToNormalizedLocation(ouzel::Vector2(x, y)));
    }

    JNIEXPORT void JNICALL Java_lv_elviss_ouzel_OuzelLibJNIWrapper_handleActionCancel(JNIEnv* env, jclass cls, jint pointerId, jfloat x, jfloat y)
    {
        OUZEL_UNUSED(env);
        OUZEL_UNUSED(cls);

        ouzel::sharedEngine->getInput()->touchCancel(static_cast<uint64_t>(pointerId),
                                                     ouzel::sharedEngine->getRenderer()->screenToNormalizedLocation(ouzel::Vector2(x, y)));
    }
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "globalconfig.h"

#include "factory.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "backendinterface.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

namespace Phonon
{
class QSettingsGroup
{
    public:
        QSettingsGroup(const QSettings *settings, const QString &name)
            : m_s(settings),
            m_group(name + QLatin1Char('/'))
        {
        }

        template<typename T>
        inline T value(const QString &key, const T &def) const
        {
            return qvariant_cast<T>(value(key, QVariant::fromValue(def)));
        }

        QVariant value(const QString &key, const QVariant &def) const
        {
            return m_s->value(m_group + key, def);
        }

    private:
        const QSettings *const m_s;
        QString m_group;
};

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice_") + Factory::identifier());

    //First we lookup the available devices directly from the backend
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
    if (!backendIface) {
        return QList<int>();
    }
    QList<int> defaultList = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);

    //Now the list from m_config
    const QString categoryKey = QLatin1String("Category") + QString::number(static_cast<int>(category));
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());
    if (deviceList.isEmpty()) {
        //try to read from global group for defaults
        const QSettingsGroup globalConfig(&m_config, QLatin1String("AudioOutputDevice"));
        deviceList = globalConfig.value(categoryKey, QList<int>());
    }

    QMutableListIterator<int> i(deviceList);
    while (i.hasNext())
        if (0 == defaultList.removeAll(i.next()))
            //if there are devices in m_config that the backend doesn't report, remove them from the list
            i.remove();
    //if the backend reports more devices that are not in m_config append them to the list
    if (defaultList.size() > 1) {
        // initial order is important
        QMap<int, int> orderedList;
        QList<int> noPrefList; //list with no preference
        foreach (int index, defaultList) {
            const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(Phonon::AudioOutputDeviceType, index);
            QVariant var = properties.value("initialPreference");
            if (var.isValid())
                orderedList.insertMulti(-var.toInt(), index);
            else
                noPrefList += index;
        }
        defaultList = orderedList.values() + noPrefList;
    }
    deviceList += defaultList;

    return deviceList;
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

/*QList<int> GlobalConfig::audioCaptureDeviceList() const
{
    //First we lookup the available devices directly from the backend
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
    if (!backendIface) {
        return QList<int>();
    }
    QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);

    QList<int> defaultList = deviceIndexes;

    //Now the list from m_config
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice_") +
            Factory::identifier());
    QList<int> deviceList = backendConfig.value(QLatin1String("DeviceOrder"), QList<int>());
    if (deviceList.isEmpty()) {
        //try to read from global group for defaults
        const QSettingsGroup globalConfig(&m_config, QLatin1String("AudioCaptureDevice"));
        deviceList = globalConfig.value(QLatin1String("DeviceOrder"), defaultList);
    }

    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            //if there are devices in m_config that the backend doesn't report, remove them from the list
            i.remove();
        }
    }
    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

int GlobalConfig::audioCaptureDevice() const
{
    return audioCaptureDeviceList().first();
}*/

} // namespace Phonon

#include "moc_globalconfig.cpp"

// vim: sw=4 ts=4
<commit_msg>- remove initialPreference reordering as it's unnecessary now that the list returned from the backend already is in initialPreference order - filter out devices marked as isAdvanced if advanced devices should be hidden - if there's no order defined for a given category look for the order of NoCategory and only then use the initial order<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2006 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "globalconfig.h"

#include "factory.h"
#include "objectdescription.h"
#include "phonondefs_p.h"
#include "backendinterface.h"

#include <QtCore/QList>
#include <QtCore/QVariant>

namespace Phonon
{
class QSettingsGroup
{
    public:
        QSettingsGroup(const QSettings *settings, const QString &name)
            : m_s(settings),
            m_group(name + QLatin1Char('/'))
        {
        }

        template<typename T>
        inline T value(const QString &key, const T &def) const
        {
            return qvariant_cast<T>(value(key, QVariant::fromValue(def)));
        }

        QVariant value(const QString &key, const QVariant &def) const
        {
            return m_s->value(m_group + key, def);
        }

        bool hasKey(const QString &key) const
        {
            return m_s->contains(m_group + key);
        }

    private:
        const QSettings *const m_s;
        QString m_group;
};

GlobalConfig::GlobalConfig(QObject *parent)
    : QObject(parent)
    , m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
{
}

GlobalConfig::~GlobalConfig()
{
}

static void filterAdvanced(BackendInterface *backendIface, QList<int> *list)
{
    QMutableListIterator<int> it(*list);
    while (it.hasNext()) {
        const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(Phonon::AudioOutputDeviceType, it.next());
        QVariant var = properties.value("isAdvanced");
        if (var.isValid() && var.toBool()) {
            it.remove();
        }
    }
}

QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category) const
{
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
    const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
    const bool hideAdvancedDevices = generalGroup.value(QLatin1String("HideAdvancedDevices"), true);

    //First we lookup the available devices directly from the backend
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
    if (!backendIface) {
        return QList<int>();
    }

    // this list already is in default order (as defined by the backend)
    QList<int> defaultList = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
    if (hideAdvancedDevices) {
        filterAdvanced(backendIface, &defaultList);
    }

    QString categoryKey = QLatin1String("Category") + QString::number(static_cast<int>(category));
    if (!backendConfig.hasKey(categoryKey)) {
        // no list in config for the given category
        QString categoryKey = QLatin1String("Category") + QString::number(static_cast<int>(Phonon::NoCategory));
        if (!backendConfig.hasKey(categoryKey)) {
            // no list in config for NoCategory
            return defaultList;
        }
    }

    //Now the list from m_config
    QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());

    //if there are devices in m_config that the backend doesn't report, remove them from the list
    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            i.remove();
        }
    }

    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

int GlobalConfig::audioOutputDeviceFor(Phonon::Category category) const
{
    QList<int> ret = audioOutputDeviceListFor(category);
    if (ret.isEmpty())
        return -1;
    return ret.first();
}

/*QList<int> GlobalConfig::audioCaptureDeviceList() const
{
    //First we lookup the available devices directly from the backend
    BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
    if (!backendIface) {
        return QList<int>();
    }
    QList<int> deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);

    QList<int> defaultList = deviceIndexes;

    //Now the list from m_config
    //The devices need to be stored independently for every backend
    const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice_") +
            Factory::identifier());
    QList<int> deviceList = backendConfig.value(QLatin1String("DeviceOrder"), QList<int>());
    if (deviceList.isEmpty()) {
        //try to read from global group for defaults
        const QSettingsGroup globalConfig(&m_config, QLatin1String("AudioCaptureDevice"));
        deviceList = globalConfig.value(QLatin1String("DeviceOrder"), defaultList);
    }

    QMutableListIterator<int> i(deviceList);
    while (i.hasNext()) {
        if (0 == defaultList.removeAll(i.next())) {
            //if there are devices in m_config that the backend doesn't report, remove them from the list
            i.remove();
        }
    }
    //if the backend reports more devices that are not in m_config append them to the list
    deviceList += defaultList;

    return deviceList;
}

int GlobalConfig::audioCaptureDevice() const
{
    return audioCaptureDeviceList().first();
}*/

} // namespace Phonon

#include "moc_globalconfig.cpp"

// vim: sw=4 ts=4
<|endoftext|>